MicroMod Beta Testing

I wonder if their camera connector was setup for ov7670 like https://smile.amazon.com/Quickbuying-Camera-Module-OV7670-2-5V-3-0V/dp/B07H3QXZH9/

The other sparkfun board that mentions the camera... https://www.sparkfun.com/products/15170

their schematic shows ov7670

Good morning all. Not 100% sure the HB01B0 has a different pinout on the cable than the OV7670. Took a glance at the schematic and it does bring the 1.8v to camera connector/ Ordered one out of curiosity - but takes a month to get here

Just found the cable layout = looks the same. I stand corrected
 

Attachments

  • ov7725_03.jpg
    ov7725_03.jpg
    129.1 KB · Views: 50
  • Capture.jpg
    Capture.jpg
    128.9 KB · Views: 52
Morning all, I have not ordered one of those yet, especially since it is easier to debug using other OV... camera hooked up to external pins.
Looks like other options to order those, like ebay: https://www.ebay.com/itm/1919255698...73&rlsatarget=pla-1068323855510&abcId=9300523 or BangGood or...

Yep - I agree with the debugging aspect. Figured what the heck its going to take forever anyway.

I did download your latest OV767x changes and hooked it up to the ATP with a ILI9341. And it worked rather nicely. Only one thing of note: writesubimageRect is only in you ILI9341_t3n library :) Heres a screen shot:
IMG-0342.png
 
Morning again, Yeah I probably should go back to using ILI9341 library on it... But as you were doing ST... I hooked up ST and starting adding support for it.

I have version of ST7735_t3 with the subrect stuff integrated. Not sure if it works, as I set the camera up for 320x240 same as the display...

EDIT: Pushed up the ST... changes in branch: https://github.com/KurtE/ST7735_t3/tree/writeSubImageRect
 
Last edited:
Morning again, Yeah I probably should go back to using ILI9341 library on it... But as you were doing ST... I hooked up ST and starting adding support for it.

I have version of ST7735_t3 with the subrect stuff integrated. Not sure if it works, as I set the camera up for 320x240 same as the display...

Had a feeling - thank you. Going crazy with that HB01B0. I need a sanity check on the data capture at some point but going to keep playing. Maybe I will post what I see. Think I have a strand or 2 of hair left :) I moved over the ILI9341 since it just seemed simpler than trying to add the code to the ST7789 :) Just used the ST7789 since I already had it out and took less space on the desk :) Looks like a nice function to add to the libraries as time permits.
 
All -- think its need a sanity check at this point on what I am doing so here goes the first sanity check.

In the HMB01B0 function I set up the VSYNC/HREF/PCLK/Databus pins as:
Code:
	pinMode(VSYNC_PIN, INPUT_PULLDOWN); // VSYNC Pin
	pinMode(PCLK_PIN, INPUT_PULLDOWN);  //PCLK
	pinMode(HSYNC_PIN, INPUT_PULLDOWN);  //HSYNC
	
	//Thanks to @luni for how to read 8bit port	\
	//https://forum.pjrc.com/threads/66771-MicroMod-Beta-Testing?p=275567&viewfull=1#post275567
	//This interesting too: https://forum.pjrc.com/threads/57698-Parallel-IO-is-it-possible?p=216501&viewfull=1#post216501
	//for (uint8_t pin : {G0, G1, G2, G3, G4, G5, G6, G7})
	//{
	//	pinMode(pin, INPUT_PULLUP);
	//}
	pinMode(mmBus, INPUT_PULLUP);
Note for the data bus I am using @luni's micromod.

To determine the clock pin states I found the following - forgot where now - that is used later to determine frame and line start:
Code:
	_vsyncMask = digitalPinToBitMask(VSYNC_PIN);
    _hrefMask = digitalPinToBitMask(HSYNC_PIN);
    _pclkMask = digitalPinToBitMask(PCLK_PIN);

    _vsyncPort = portInputRegister(digitalPinToPort(VSYNC_PIN));
    _hrefPort = portInputRegister(digitalPinToPort(HSYNC_PIN));
    _pclkPort = portInputRegister(digitalPinToPort(PCLK_PIN));
After all this I enable the power and turn on the clock per Paul's initial setup:
Code:
	// turn on power to camera (1.8V - might be an issue?)
	pinMode(EN_PIN, OUTPUT);
	digitalWrite(EN_PIN, HIGH);
	delay(10);

	// turn on MCLK
	OMV_XCLK_FREQUENCY = 12000000;
	analogWriteFrequency(MCLK_PIN, OMV_XCLK_FREQUENCY);
	analogWrite(MCLK_PIN, 128);
	delay(5);
The 12Mhz clock is based on what I am seeing in other libs for the HB01B0.

So the question I have for everyone is if this is correct and if not what do I have to do to correct. Next up the getting the frame from the camera.

EDIT: forgot the pin assignments I make in the .h file:
Code:
  	uint8_t VSYNC_PIN = 33;
	uint8_t PCLK_PIN = 8;
	uint8_t HSYNC_PIN = 32;
	uint8_t MCLK_PIN = 7;
	uint8_t EN_PIN = 2;
 
Had a feeling - thank you. Going crazy with that HB01B0. I need a sanity check on the data capture at some point but going to keep playing. Maybe I will post what I see. Think I have a strand or 2 of hair left :) I moved over the ILI9341 since it just seemed simpler than trying to add the code to the ST7789 :) Just used the ST7789 since I already had it out and took less space on the desk :) Looks like a nice function to add to the libraries as time permits.
I think we cross posted... Pushed up branch with those functions. At some point soon, may switch to ILI9341, but started with Adafruit board as I also have the SD card setup for MTP, MSC...

Looks like Sparkfun's ATP carrier board lacks any sort of USB host current limiting or even a 100 or 150 uF capacitor.

As far as I can tell none of their other boards do USB host, so they're probably not yet familiar with the requirements for hot plugging USB.

Paul,

I am curious about the differences between the USB-B versus -C. Doing a quick look at a couple sites, like:https://www.digikey.com/en/articles...c-and-using-power-delivery-for-rapid-charging

It looks like Type-B has a max of .5amp... But Type-C has Max of 3amp or another one 5 Amp. So wondering if there is a different chip for doing hot plugging for USB-C or if having 3 amps (or in their case through a 2 amp fuse) is sufficient that you don't need that other chip. However I would think you might still need/want a good size cap. Also don't have any idea of what limitations USB-C has when plugged in through a USB A connection to different things like Hubs, computers... My newer IPads have USB-C, but they come with their own chargers and cables where are USB-C on both ends.

Looks like lots more to learn!
 
@KurtE
Just pulled down the updated library with that function will give it a try later. Planning on attaching the SDCard as well but have to find more jumpers :)
 
@KurtE
Just pulled down the updated library with that function will give it a try later. Planning on attaching the SDCard as well but have to find more jumpers :)
Know the feeling, but with the Adafruit board just needed one extra one ;)

Starting to update the DMA code in that library to the right pins, ...
Once that looks reasonable, then may try something completely different and try out the FlexIO
 
msj513 said:
All -- think its need a sanity check at this point on what I am doing so here goes the first sanity check.

In the HMB01B0 function I set up the VSYNC/HREF/PCLK/Databus pins as:
Code:
pinMode(VSYNC_PIN, INPUT_PULLDOWN); // VSYNC Pin
pinMode(PCLK_PIN, INPUT_PULLDOWN); //PCLK
pinMode(HSYNC_PIN, INPUT_PULLDOWN); //HSYNC

//Thanks to @luni for how to read 8bit port \
//https://forum.pjrc.com/threads/66771-MicroMod-Beta-Testing?p=275567&viewfull=1#post275567
//This interesting too: https://forum.pjrc.com/threads/57698-Parallel-IO-is-it-possible?p=216501&viewfull=1#post216501
//for (uint8_t pin : {G0, G1, G2, G3, G4, G5, G6, G7})
//{
// pinMode(pin, INPUT_PULLUP);
//}
pinMode(mmBus, INPUT_PULLUP);
Note for the data bus I am using @luni's micromod.

I got my mm4 board and did some tests with the mmBus functionality. Looks like there is a glitch with the overwritten pinMode(mmBus, INPUT_PULLDOWN). I currently don't know why, but it somehow activates some latching on the pins. Very weird. Anyway, if I change pinMode(mmBus,INPUT_PULLDOWN) to mmBus.pinMode(INPUT_PULLDOWN) it works as it should.
 
I got my mm4 board and did some tests with the mmBus functionality. Looks like there is a glitch with the overwritten pinMode(mmBus, INPUT_PULLDOWN). I currently don't know why, but it somehow activates some latching on the pins. Very weird. Anyway, if I change pinMode(mmBus,INPUT_PULLDOWN) to mmBus.pinMode(INPUT_PULLDOWN) it works as it should.

Thanks for the info @luni. Just made the change made a little difference but not much. It almost looks like the start or the line gets shifted on every read. Have to get my head sorted out out this one.

EDIT: There was one question. The bit order is for the byte is bit8 to bit0 correct?
 
Just another guess, did you try INPUT instead of INPUT_PULLDOWN? If I understand correctly the camera works with 1.8V? Maybe this together with the internal pulldowns is just borderline?
 
@luni
Was pretty sure about the bit order but never hurts to double check when debugging. I'll changing to input and see what happens.
 
Note with the OV7670 and test code, after it receives the bytes, it needed to swap the bytes for each pixel... Not sure about this one...

Also again maybe it is my jumper cords or the OV76 or... but the VSync signal has noise. So the current stuff when it waits for the signal to go High and then low, the code now
has an elapsedMicros in there and only process if > 100 micros..
 
Note with the OV7670 and test code, after it receives the bytes, it needed to swap the bytes for each pixel... Not sure about this one...

Also again maybe it is my jumper cords or the OV76 or... but the VSync signal has noise. So the current stuff when it waits for the signal to go High and then low, the code now
has an elapsedMicros in there and only process if > 100 micros..

Changed the bus to input but did not change enough to get a signal. Was just going to go through your code to see how you handled vsynch etc. With monochrome images if I read the spec right it should only be 1 byte per pixel. If its 2bytes for grayscale then I am lost :) For color it would be 2bytes but its bayer so not so straight forward.

Right now I have two methods that I am testing. The first from openMV to get a snapshot and the second from Sparkfuns lib that does the same:
Code:
// This is the default snapshot function, which can be replaced in sensor_init functions.
int HM01B0::sensor_snapshot(uint8_t *image)
{
	uint8_t val;
    
    uint32_t _width  = w;
    uint32_t _height = h;
    int bytesPerRow  = _width * 2 ; // Always read 2 BPP
    bool _grayscale = (pixformat == PIXFORMAT_GRAYSCALE);

    // Compress the framebuffer for the IDE preview, only if it's not the first frame,
    // the framebuffer is enabled and the image sensor does not support JPEG encoding.
    // Note: This doesn't run unless the IDE is connected and the framebuffer is enabled.
    //framebuffer_update_jpeg_buffer(NULL);
	
	Serial.printf("SensorSnapshot (w,h), bytes/row %d: %d, %d\n", _width, _height, bytesPerRow);
	//Serial.printf("Grayscale: %d\n", _grayscale);
	Serial.println("Sending Single FrameRequest");
	set_mode(HIMAX_MODE_STREAMING_NFRAMES, 1);
	
    noInterrupts();

    // Falling edge indicates start of frame
    while ((*_vsyncPort & _vsyncMask) == 0); // wait for HIGH
    while ((*_vsyncPort & _vsyncMask) != 0); // wait for LOW
	//Serial.println("Start of Frame");

    for (uint32_t i = 0; i < _height; i++) {
        // rising edge indicates start of line
        while ((*_hrefPort & _hrefMask) == 0); // wait for HIGH
			//Serial.printf("Start of Line, %d\n", i);
			for (int j = 0; j < bytesPerRow; j++) {
				// rising edges clock each data byte
				while ((*_pclkPort & _pclkMask) != 0); // wait for LOW

				val = mmBus;             // read 8bit value from bus
				
				if (!(j & 1) && !_grayscale) {
					*image++ = val;
				}
				while ((*_pclkPort & _pclkMask) == 0); // wait for HIGH
			}
        while ((*_hrefPort & _hrefMask) != 0); // wait for LOW
    }

    interrupts();
	/*
    // Fix the BPP.
    switch (sensor->pixformat) {
        case PIXFORMAT_GRAYSCALE:
            MAIN_FB()->bpp = 1;
            break;
        case PIXFORMAT_YUV422:
        case PIXFORMAT_RGB565: {
            MAIN_FB()->bpp = 2;
            if (SENSOR_HW_FLAGS_GET(sensor, SWNSOR_HW_FLAGS_RGB565_REV)) {
                unaligned_memcpy_rev16(MAIN_FB()->pixels, MAIN_FB()->pixels, _width*_height);
            }
            break;
        }
        case PIXFORMAT_BAYER:
            MAIN_FB()->bpp = 3;
            break;
        default:
            MAIN_FB()->bpp = -1;
            break;
    }

    // Set the user image.
    if (image != NULL) {
        image->w = MAIN_FB()->w;
        image->h = MAIN_FB()->h;
        image->bpp = MAIN_FB()->bpp;
        image->pixels = MAIN_FB()->pixels;
    }
	*/
	
	Serial.println("Turning on Streaming");
		set_mode(HIMAX_MODE_STREAMING, 0);

    return 0;
}
the second from the Sparkfun lib:
Code:
uint8_t HM01B0::blocking_read_oneframe(uint8_t *pui8Buffer, uint32_t ui32BufferLen)
{
    uint32_t    ui32Err         = 0;
    uint32_t    ui32Idx         = 0x00;

    uint32_t    ui32HsyncCnt    = 0x00;
	Serial.println("Blocking Read One Frame");
	
	set_mode(HIMAX_MODE_STREAMING_NFRAMES, 1);
	delay(10);

    while((ui32HsyncCnt < 324))
    {
        while (0x00 == digitalReadFast(HSYNC_PIN));

        // read one row
        while(digitalReadFast(HSYNC_PIN))
        {
            while(0x00 == digitalReadFast(PCLK_PIN));

            *(pui8Buffer + ui32Idx++) = mmBus;

            if (ui32Idx == ui32BufferLen) {
                goto end;
            }

            while(digitalReadFast(PCLK_PIN));
        }

        ui32HsyncCnt++;
    }

end:
	set_mode(HIMAX_MODE_STREAMING, 0);
    return ui32Err;

}
The second actually looks like its giving better results.
 
All
Looks like I got it partially working. I now can get a picture on startup but if I try and take another snapshot in the loop nothing shows? Have to figure that one. Here is the initial screen shot:
IMG-0345.png

Not going to post the updates yet want to clean up all the test code.

For the inquiring mind according to the spec the image size is 324x244 but if I use that the image gets skewed as you saw. Changing it to 320x240 got me the picture. Also looks like I had an error in my snap shot function so I used a version what was in the OV7670 since it was almost the same as the one I was using. Oh the wires you see are the jumper wires going across the camera :)

So at least now we know it works.
 
@mjs513 Looking like progress! :D

Today I am having a lower productivity day with this.

I am playing with the OV7670 DMA input. Having some progress, finding out that the ST7735 code may have some issues or comparability with ILI9341_t3n, DMA running nothing output,

I was using the writeRect(CENTER, CENTER, width, height... and nothing showed up. I think with ILI... have it compute the needed start_x and start_y so time to compare and maybe fix.

Edit pushed up fix for CENTER in ST... will probably merge into my PR branch...

Also pushed up WIP on OV7670
 
Last edited:
@mjs513 Looking like progress! :D

Today I am having a lower productivity day with this.

I am playing with the OV7670 DMA input. Having some progress, finding out that the ST7735 code may have some issues or comparability with ILI9341_t3n, DMA running nothing output,

I was using the writeRect(CENTER, CENTER, width, height... and nothing showed up. I think with ILI... have it compute the needed start_x and start_y so time to compare and maybe fix.

Edit pushed up fix for CENTER in ST... will probably merge into my PR branch...

Also pushed up WIP on OV7670
Sounds like you have been busy and making progress as well. Anyway's got the lib cleaned up, still more to do, and have a cleaned up sketch that allows you do do a screen capture and put it in continuous mode. Takes a little extra time since I have to convert to grayscale to color565. Am attaching if you want to play.
 

Attachments

  • HM01B0.zip
    15.8 KB · Views: 57
And for a display? showing
Code:
#include <ST7735_t3.h> // Hardware-specific library
#include <ST7789_t3.h>
#include <SPI.h>
#include <SD.h>


#define TFT_DC   1 
#define TFT_CS   5  
#define TFT_RST  0

ST7789_t3 tft = ST7789_t3(TFT_CS, TFT_DC, TFT_RST);

ST7789 Wired on SPI with those control pins?

installed or updated lib?
 
Ok - got on the computer to answer. Easier than using the iPhone.

Anyway I am using a Adafruit 320x240 ST7789 display for the testing. One because it was handy and more importantly didn't require a 5v pin. For whatever reason Sparkfun didn't break out the 5v pin to a edge pin only 3.3v. I am using the installed ST7789 library, although will probably swapped it out for @KurtE's updated ST7789 library so I can use the subimageWriteRect function tomorrow. The display is wired to COPI, CIPO and SCK pins on the ML carrier board and using the control pins you listed:
Code:
#define TFT_DC   1 
#define TFT_CS   5  
#define TFT_RST  0

ST7789_t3 tft = ST7789_t3(TFT_CS, TFT_DC, TFT_RST);
Image quality needs some work but that is another project :)
 
Never got one of those 7789's - found a 7735 but size is off. ILI9341's galore ...
Now you know why going to update the lib to use the subimage function so it might fix on a small display with smaller resolution. Have several ILI934's, ILI9488's etc.

Ready for sleep now so tomorrow have a couple of things to work on now that I got an image out of the camera thanks to everyone's suggestion.
1. update ST7789 library.
2. DELETED - looked at the function in rosetta code not applicable.
3. Maybe add Sparkfuns auto AE function
4. play with camera settings to improve picture.
 
Back
Top