Arduino Mega 2560 and HacroCam

I'm working with a HacroHub and a Mega 2560 for my engineering senior project and I'm having trouble with integrating some of the provided code.The base code is the HacroHub Arduino sketch at http://hacromatic.com/page/21 (zipped) and what I need to integrate is in the code block at the bottom of http://hacromatic.com/page/19. The rest of the code gets flashed to the HacroCam's firmware and I previously worked with the makers of the HC (Hacromatic) to get it integrated and flashed, but now they are no longer responding to requests for help.

So I'm hoping that one or more of the many fine, knowledgeable persons here can help me with this last major stumbling block. The base HacroHub sketch has all instances of the HacroCam object as elements of an array while the code at the second link is for only a single HacroCam object. I feel like this should be a simple fix, but somehow I'm just not coming up with it after many hours of looking at it.

I discussed a HacroCam some time ago on the forum here - HacroCam - recalculate to greyscale before sending (processing example) - Sensors - Arduino Forum -
It might contain some tips you can use.

I did read through that topic, and while it was interesting and helped me get a better idea of some of the coding it didn’t help with the issue I’m having. I actually posted a reply in that topic with a suggestion for making a change to the HacroCam’s firmware to get the camera to take pictures in greyscale rather than RGB.

I realize that it’s kind of a pain to have to download, unzip, and go over a bunch of new code so instead I’ll post the gist of it here. So here’s the original Arduino sketch provided by Hacromatic, minus the functions that make a lot of it work:

#include "HacroCam.h"
#include <avr/pgmspace.h>

#define NUM_HACROCAMS 8

byte g_debug = 0;
const byte g_bufsize = 32;
byte g_bufpos = 0;
char g_buf[g_bufsize];
byte g_nextcam = 0;
HacroCam hcams[NUM_HACROCAMS];
byte g_camidx = 0xff;

static PROGMEM prog_uint8_t crc_table[256] =
{
    0x00, 0x2f, 0x5e, 0x71, 0xbc, 0x93, 0xe2, 0xcd, 0x57, 0x78, 0x09, 0x26, 0xeb, 0xc4, 0xb5, 0x9a,
    0xae, 0x81, 0xf0, 0xdf, 0x12, 0x3d, 0x4c, 0x63, 0xf9, 0xd6, 0xa7, 0x88, 0x45, 0x6a, 0x1b, 0x34,
    0x73, 0x5c, 0x2d, 0x02, 0xcf, 0xe0, 0x91, 0xbe, 0x24, 0x0b, 0x7a, 0x55, 0x98, 0xb7, 0xc6, 0xe9,
    0xdd, 0xf2, 0x83, 0xac, 0x61, 0x4e, 0x3f, 0x10, 0x8a, 0xa5, 0xd4, 0xfb, 0x36, 0x19, 0x68, 0x47,
    0xe6, 0xc9, 0xb8, 0x97, 0x5a, 0x75, 0x04, 0x2b, 0xb1, 0x9e, 0xef, 0xc0, 0x0d, 0x22, 0x53, 0x7c,
    0x48, 0x67, 0x16, 0x39, 0xf4, 0xdb, 0xaa, 0x85, 0x1f, 0x30, 0x41, 0x6e, 0xa3, 0x8c, 0xfd, 0xd2,
    0x95, 0xba, 0xcb, 0xe4, 0x29, 0x06, 0x77, 0x58, 0xc2, 0xed, 0x9c, 0xb3, 0x7e, 0x51, 0x20, 0x0f,
    0x3b, 0x14, 0x65, 0x4a, 0x87, 0xa8, 0xd9, 0xf6, 0x6c, 0x43, 0x32, 0x1d, 0xd0, 0xff, 0x8e, 0xa1,
    0xe3, 0xcc, 0xbd, 0x92, 0x5f, 0x70, 0x01, 0x2e, 0xb4, 0x9b, 0xea, 0xc5, 0x08, 0x27, 0x56, 0x79,
    0x4d, 0x62, 0x13, 0x3c, 0xf1, 0xde, 0xaf, 0x80, 0x1a, 0x35, 0x44, 0x6b, 0xa6, 0x89, 0xf8, 0xd7,
    0x90, 0xbf, 0xce, 0xe1, 0x2c, 0x03, 0x72, 0x5d, 0xc7, 0xe8, 0x99, 0xb6, 0x7b, 0x54, 0x25, 0x0a,
    0x3e, 0x11, 0x60, 0x4f, 0x82, 0xad, 0xdc, 0xf3, 0x69, 0x46, 0x37, 0x18, 0xd5, 0xfa, 0x8b, 0xa4,
    0x05, 0x2a, 0x5b, 0x74, 0xb9, 0x96, 0xe7, 0xc8, 0x52, 0x7d, 0x0c, 0x23, 0xee, 0xc1, 0xb0, 0x9f,
    0xab, 0x84, 0xf5, 0xda, 0x17, 0x38, 0x49, 0x66, 0xfc, 0xd3, 0xa2, 0x8d, 0x40, 0x6f, 0x1e, 0x31,
    0x76, 0x59, 0x28, 0x07, 0xca, 0xe5, 0x94, 0xbb, 0x21, 0x0e, 0x7f, 0x50, 0x9d, 0xb2, 0xc3, 0xec,
    0xd8, 0xf7, 0x86, 0xa9, 0x64, 0x4b, 0x3a, 0x15, 0x8f, 0xa0, 0xd1, 0xfe, 0x33, 0x1c, 0x6d, 0x42
};

void setup()
{
    Serial.begin(230400);
}

void loop()
{
    byte available = Serial.available();
    if (available)
    {
        byte freespace = g_bufsize-g_bufpos;
        byte toread = (available > freespace) ? freespace : available;
        for (byte i = 0; i < toread; ++i)
        {
            byte b = Serial.read();
            if (b == '\r')
            {
                processMessage();
            }
            else if (b == '\n')
            {
                if (g_bufpos)
                    processMessage();
            }
            else
            {
                if (g_debug && (b == 127 || b == 8))
                {
                    if (g_bufpos)
                    {
                        Serial.write(8);
                        g_buf[--g_bufpos] = 0;
                    }
                }
                else
                {
                    if (g_debug)
                        Serial.print((char)b);
                    g_buf[g_bufpos++] = b;
                }
            }
        }
        if (g_bufpos == g_bufsize)
        {
            if (g_debug)
                Serial.println("buffer overflow");
            // Something bad happened, and we'll never execute another command
            // because the buffer is full and yet doesn't contain a complete
            // command. The only reasonable thing to do here, besides halt, is
            // to clear the buffer.
            clearBuffer();
        }
    }
}

And here’s the Arduino code given in the Line Drawings tutorial:

#include "HacroCam.h"
HacroCam hcam;

void setup()
{
    hcam.begin();
    hcam.setReadAddress(0x0);
    hcam.setWriteAddress(0x0);
    hcam.setCaptureMode(HacroCam::RGB320x240);
    uint8_t wait = hcam.capture();
    delay(1000UL*wait + 8000UL);
}

void loop()
{
}

Obviously the second code block is much simpler since it’s only designed to give the HacroCam a quick set of parameters, then take an image and wait for a while. The bigger problem is that the first code block uses an array of hcams objects while the second uses a single hcam object. So am I just making this a lot harder than it needs to be? Should I just be able to use the stock Arduino sketch to access my HacroCam with modified firmware?

robtillaart? robvoi?

Anybody? Little help? :sunglasses:

So am I just making this a lot harder than it needs to be? Should I just be able to use the stock Arduino sketch to access my HacroCam with modified firmware?

think so, you could just use an index (typically 0 for the first) to address your hcam.

void setup()
{
    hcam[0].begin();
    hcam[0].setReadAddress(0x0);
    hcam[0].setWriteAddress(0x0);
    hcam[0].setCaptureMode(HacroCam::RGB320x240);
    uint8_t wait = hcam[0].capture();

    delay(1000UL*wait + 8000UL);
}

void loop()
{
}

(disclaimer: not owning a hcam :wink:

I've actually tried a similar merging of the Arduino code:

void setup()
{
    Serial.begin(230400);
    hcams[0].begin();
    hcams[0].setReadAddress(0x0);
    hcams[0].setWriteAddress(0x0);
    hcams[0].setCaptureMode(HacroCam::RGB320x240);
    uint8_t wait = hcams[0].capture();
    delay(1000UL*wait + 8000UL);
}

But it did not work and I'm not sure now that I even need to do any of it. I think the original HacroCam code should allow me to do everything I need to do after thinking about it from a new angle last night. Like the site says "The Arduino code I used simply grabs a picture on power up," which is the second code box. So it shouldn't need anything fancy, but without a screen to output the image to I don't have a way of knowing if everything's working.

The original HacroCam Arduino sketch (called HacroHub) includes all of the functionality to talk to as many as eight distinct HCs using a terminal program (CoolTerm is their preference). I've been using CoolTerm the whole time with the settings shown in their own tutorial and it's worked every time except for being able to talk to my HC after I flash the new firmware. Once I do that I can no longer talk to it with CoolTerm and according to the person I was emailing, I shouldn't have that problem.

When that started happening I figured there was something wrong with my firmware coding, but now I'm using coding provided directly by the manufacturer. So... now I'm not sure what to look at!

I tried to hook up my Hacrocam to my Mega. It didn't find the cam. I thought it might be a compatibility issue as I used it with my UNO before. But as you use it with a Mega it must be a Hardware problem. If I get it to work again I can do some testing.

And yes - the developers stopped answering requests.

Thanks for any help you can give robvoi. It has become extremely difficult figuring things out on my own.

To connect your HC to your Mega you can either mount it as a shield or off by itself because all that really needs to be connected between the two are +5V, GND, SDA, and SCL. 5V and GND match up between the HC and Mega, but SDA and SCL don't. SDA is pin 4 (the header next to 5V and GND) on the HC and pin 20 on the Mega (in the Communication section at the top right corner). SCL is pin 5 on the HC (same header as pin 4) and pin 21 on the Mega. So if the HC is mounted as a shield you only need jumpers between HC pins 4 & 5 and Mega pins 20 & 21. If not mounted you also need 5V & GND jumpers. After that everything is the same between Mega and Uno according to Brian at Hacromatic (from back when he was available).

I've been struggling away at this almost every night and I'm pretty sure I've got it down to just one problem. To do the edge detection processing you have to have a jumper across the two-pin header, but when that's on you can't use the serial TX pin. Everything has to go over the Mega I2C (SDA/SCL) pins but how do I view the final image stored in SRAM? The last thing Brian mentioned was using Processing but he didn't give any specifics. What Processing sketch would you recommend?

Also I’ve tried running the provided Processing sketch from Hacromatic (HacroCamDemo.pde) but I keep getting the error code below:

java.lang.NullPointerException
	at processing.serial.Serial.write(Unknown Source)
	at processing.serial.Serial.write(Unknown Source)
	at HacroCamDemo$HacroCam.<init>(HacroCamDemo.java:43)
	at HacroCamDemo.setup(HacroCamDemo.java:592)
	at processing.core.PApplet.handleDraw(PApplet.java:2280)
	at processing.core.PGraphicsJava2D.requestDraw(PGraphicsJava2D.java:243)
	at processing.core.PApplet.run(PApplet.java:2176)
	at java.lang.Thread.run(Thread.java:662)
java.lang.NullPointerException
	at processing.serial.Serial.write(Unknown Source)
	at processing.serial.Serial.write(Unknown Source)
	at HacroCamDemo$HacroCam.<init>(HacroCamDemo.java:44)
	at HacroCamDemo.setup(HacroCamDemo.java:592)
	at processing.core.PApplet.handleDraw(PApplet.java:2280)
	at processing.core.PGraphicsJava2D.requestDraw(PGraphicsJava2D.java:243)
	at processing.core.PApplet.run(PApplet.java:2176)
	at java.lang.Thread.run(Thread.java:662)
java.lang.NullPointerException
	at processing.serial.Serial.write(Unknown Source)
	at processing.serial.Serial.write(Unknown Source)
	at HacroCamDemo$HacroCam.sendCmd(HacroCamDemo.java:508)
	at HacroCamDemo$HacroCam.begin(HacroCamDemo.java:59)
	at HacroCamDemo.setup(HacroCamDemo.java:594)
	at processing.core.PApplet.handleDraw(PApplet.java:2280)
	at processing.core.PGraphicsJava2D.requestDraw(PGraphicsJava2D.java:243)
	at processing.core.PApplet.run(PApplet.java:2176)
	at java.lang.Thread.run(Thread.java:662)
java.lang.NullPointerException
	at processing.serial.Serial.write(Unknown Source)
	at HacroCamDemo$HacroCam.sendCmd(HacroCamDemo.java:509)
	at HacroCamDemo$HacroCam.begin(HacroCamDemo.java:59)
	at HacroCamDemo.setup(HacroCamDemo.java:594)
	at processing.core.PApplet.handleDraw(PApplet.java:2280)
	at processing.core.PGraphicsJava2D.requestDraw(PGraphicsJava2D.java:243)
	at processing.core.PApplet.run(PApplet.java:2176)
	at java.lang.Thread.run(Thread.java:662)

The code that’s highlighted is m_serial.write((byte)checksum) in the function below:

private void sendCmd(String str)
    {
        int checksum = crc(str.getBytes());
        m_serial.write(str);
        m_serial.write((byte)checksum);
        m_serial.write("\r\n");
        delay(150);
    }

Does anyone know what could be causing that error? My guess is that it’s a result of a change between Processing v2.0a6 and 2.0.2 since it worked with the previous version according to http://hacromatic.com/page/24.

You use the 32 Bit Version of Processing? The 64 Bit version doesn't support Serial communication.
Did you put in the correct COM port name?

My guess is that the com port is not correctly connected. Due to one of the reasons above.

I did make the mistake of using the 64-bit version of Processing at first, but I'd already figured out that I need to use the 32-bit version instead. I also thought I'd double-checked to make sure that I had the right COM port in the Processing sketch but I just found out that I was using the wrong one. With the correct port it runs correctly so thanks for making me doubt myself just enough. :wink:

So where should I expect to find the results of running the Processing sketch? Does it save images somewhere or should it be automatically displaying them?

The demo sketch displays the image exactly once when started. You need to restart it when you want a new picture. At least that's what I remember.

Not being familiar with Processing at all, I wasn't sure how to expect it to display the image. But I found and ran a quick example that displays an image stored in %userprofile%\Documents\Processing[sketch_name]\data.

Unfortunately, when I run the HacroCamDemo.pde sketch with only the COM port changed to match my Arduino and the "pointillism" effect disabled I still get nothing. The bottom of the Processing window says

Stable Library
=========================================
Native lib Version = RXTX-2.1-7
Java lib Version   = RXTX-2.1-7

But with my HC plugged in as a shield and the I2C pins connected correctly that's all that happens. The Processing sketch should be telling the HC to capture a new image whenever I click Run? Because neither that nor pushing the shoot switch on the HC result in any image being shown.

Another minor update: I’ve also been working at getting the HacroCam to take grayscale images rather than RGB but was getting nowhere with the code given at http://hacromatic.com/page/19. It turns out the tutorial gave incorrect register values for CAM_REG3. It says:

To change to YUV, replace this line:

const uint8_t  CAM_REG3[NUM_MODES]      = { 0, 0B11001110, 0B11000110, 0B11000010 };

with this

const uint8_t  CAM_REG3[NUM_MODES]      = { 0, 0B11001110, 0B11000100, 0B11000010 };

I.e., change the third array element’s second bit from 1 to 0, which just makes images all jacked up. After much trial and error I’ve found that instead of changing the second bit from 1 to 0, the second bit should remain 1 and the first bit should be changed from 0 to 1. So the line should actually be changed to:

const uint8_t  CAM_REG3[NUM_MODES]      = { 0, 0B11001110, 0B11000111, 0B11000010 };

Examples are below.

00006.jpg

00017.jpg

grey scale image looks good!

That's what the original code was supposed to change first and foremost in order to do the image processing, but for whatever reason the site's tutorial and the guy I was getting help from gave me the wrong code. The only thing I can think of as to why it no longer works is that maybe the HacroCam began using a different microprocessor version that had changed how its registers are modified.

Anyway, now that that's figured out I need to work through the problem of being able to fully communicate between my HacroCam and Mega over I2C. Again, everything looks like it should work exactly as shown on their tutorial, without extra modifications, but it just doesn't. Based on the fact that communication works perfectly when I don't make any changes to the HacroCam's firmware and that the only changes to the firmware are to modify a single register (and only one bit is changed there), the addition of four functions, and the addition of a line that calls the first function, I'm wondering if the register change is the problem again.

I didn't follow what problems you have with the cam and the MEGA. But as stated my cam didn't work either when I connected it to the mega. It worked with the Uno. Still didn't have time to cross check with the Uno again.
I'll try it in the next days.

I appreciate your help. Just make sure you connect pins 4 and 5 from the HacroCam to pins 20 and 21, respectively, on the Mega since the Mega's SDA and SCL pins are not the same as with the Uno.

Hello all

I have bought the camera circuit from hacromatic too.
But the downloadpage is down and so I cannot get the Software for it.

Do somebody of you have the Software and can post it?

THX Martin

Hi,

I don't have the software. But I uploaded a custom/enhanced version of the most important a part of it in this topic:
http://forum.arduino.cc/index.php?PHPSESSID=9etnterkc1vvmfnb22fgjlctj7&topic=141081.msg1062759#msg1062759

Regards,
Robert