Combining two bit of code.

Hi,
Im trying to combine the a BlinkM command (an I2C LED) code and the Standard analogue IN code from firmata.
I'v tryed to combine the void loop's ect and it didnt come up with any errors but when I try to control the RGB on the BlinkM or get a reading from the analogue in's I get nothing.

Has anyone worked with these two things before?????

To make it even harder I'm then gonna change the 16 BlinkM's to have 16 different Serial numbers so they can be controlled separately with Max MSP but thats the next hurdle.

Thanks

Post the code. Without it, there's no chance to help you.

Korman

sorry, was a bit worried that it was a bit long. here are the two codes:-

Firmata

/* This firmware supports as many analog ports as possible, all analog inputs,
 * four PWM outputs, and two with servo support.
 *
 * This example code is in the public domain.
 */
#include <Servo.h>
#include <Firmata.h>

/*==============================================================================
 * GLOBAL VARIABLES
 *============================================================================*/

/* servos */
Servo servo9, servo10; // one instance per pin
/* analog inputs */
int analogInputsToReport = 0; // bitwise array to store pin reporting
int analogPin = 0; // counter for reading analog pins
/* timer variables */
unsigned long currentMillis;     // store the current value from millis()
unsigned long previousMillis;    // for comparison with currentMillis


/*==============================================================================
 * FUNCTIONS                                                                
 *============================================================================*/

void analogWriteCallback(byte pin, int value)
{
    switch(pin) {
    case 9: servo9.write(value); break;
    case 10: servo10.write(value); break;
    case 3: 
    case 5: 
    case 6: 
    case 11: // PWM pins
        analogWrite(pin, value); 
        break;
    }
}
// -----------------------------------------------------------------------------
// sets bits in a bit array (int) to toggle the reporting of the analogIns
void reportAnalogCallback(byte pin, int value)
{
    if(value == 0) {
        analogInputsToReport = analogInputsToReport &~ (1 << pin);
    }
    else { // everything but 0 enables reporting of that pin
        analogInputsToReport = analogInputsToReport | (1 << pin);
    }
    // TODO: save status to EEPROM here, if changed
}

/*==============================================================================
 * SETUP()
 *============================================================================*/
void setup() 
{
    Firmata.setFirmwareVersion(0, 2);
    Firmata.attach(ANALOG_MESSAGE, analogWriteCallback);
    Firmata.attach(REPORT_ANALOG, reportAnalogCallback);

    servo9.attach(9);
    servo10.attach(10);
    Firmata.begin(57600);
}

/*==============================================================================
 * LOOP()
 *============================================================================*/
void loop() 
{
    while(Firmata.available())
        Firmata.processInput();
    currentMillis = millis();
    if(currentMillis - previousMillis > 20) {  
        previousMillis += 20;                   // run this every 20ms
        for(analogPin=0;analogPin<TOTAL_ANALOG_PINS;analogPin++) {
            if( analogInputsToReport & (1 << analogPin) ) 
                Firmata.sendAnalog(analogPin, analogRead(analogPin));
        }
    }
}

tbc

Then heres the BlinkM code:-

/*
 * BlinkMCommunicator -- Communication gateway between a computer and a BlinkM
 *                       Essentially turns an Arduino to an I2C<->serial adapter
 *
 * Command format is:
 * pos description
 *  0   <startbyte>
 *  1   <i2c_addr>
 *  2   <num_bytes_to_send>
 *  3   <num_bytes_to_receive>
 *  4   <send_byte0>
 *  5..n [<send_byte1>...]
 *
 * Thus minimum command length is 5 bytes long, for reading back a color, e.g.:
 *   {0x01,0x09,0x01,0x01, 'g'}
 * Most commands will be 8 bytes long, say to fade to an RGB color, e.g.:
 *   {0x01,0x09,0x04,0x00, 'f',0xff,0xcc,0x33}
 * The longest command is to write a script line, at 12 bytes long, e.g.:
 *   {0x01,0x09,0x08,0x00, 'W',0x00,0x01,50,'f',0xff,0xcc,0x33}
 * 
 * BlinkM connections to Arduino
 * -----------------------------
 * PWR - -- gnd -- black -- Gnd
 * PWR + -- +5V -- red   -- 5V
 * I2C d -- SDA -- green -- Analog In 4
 * I2C c -- SCK -- blue  -- Analog In 5
 * 
 *
 * Note: This sketch resets the I2C address of the BlinkM.
 *       If you don't want this behavior, comment out "BlinkM_setAddress()"
 *       in setup() and change the variable "blink_addr" to your BlinkM's addr.
 *
 * 2007-8, Tod E. Kurt, ThingM, http://thingm.com/
 *
 */



#include "Wire.h"
#include "BlinkM_funcs.h"

//#define DEBUG 1

// define this if you're plugging a BlinkM directly into an Arduino,
// into the standard position on analog in pins 2-5
// otherwise you can comment it out.
#define BLINKM_ARDUINO_POWERED 1

#define CMD_START_BYTE  0x01

int blinkm_addr = 0x09;

byte serInStr[32];  // array that will hold the serial input string

int ledPin = 13;

void setup()
{
    pinMode(ledPin, OUTPUT);
    if( BLINKM_ARDUINO_POWERED ) {
        BlinkM_beginWithPower();
    } else {
        BlinkM_begin();
    }
    // FIXME:
    BlinkM_setAddress( blinkm_addr );  // comment out to not set address
    
    Serial.begin(19200); 
    byte rc = BlinkM_checkAddress( blinkm_addr );
    if( rc == -1 ) 
        Serial.println("no response");
    else if( rc == 1 ) 
        Serial.println("addr mismatch");

    Serial.println("BlinkMCommander ready");
#ifdef DEBUG
    Serial.println("DEBUG MODE");
#endif
}

void loop()
{
    int num;
    //read the serial port and create a string out of what you read
    num = readCommand(serInStr);
    if( num == 0 )   // see if we got a proper command string yet
        return;

    digitalWrite(ledPin,HIGH);  // say we're working on it
    
    byte addr    = serInStr[1];
    byte sendlen = serInStr[2];
    byte recvlen = serInStr[3];
    byte* cmd    = serInStr+4;
#ifdef DEBUG
    Serial.print(" addr:"); Serial.print(addr,HEX);
    Serial.print(" sendlen:"); Serial.print(sendlen,HEX);
    Serial.print(" recvlen:"); Serial.print(recvlen,HEX);
    Serial.print(" cmd[0..7]:"); Serial.print(cmd[0],HEX);
    Serial.print(","); Serial.print(cmd[1],HEX); 
    Serial.print(","); Serial.print(cmd[2],HEX);
    Serial.print(","); Serial.print(cmd[3],HEX);
    Serial.print(","); Serial.print(cmd[4],HEX);
    Serial.print(","); Serial.print(cmd[5],HEX);
    Serial.print(","); Serial.print(cmd[6],HEX);
    Serial.print(","); Serial.println(cmd[7],HEX);
#endif

    BlinkM_sendCmd(addr, cmd, sendlen);

    // if looking for a response, get it
    if( recvlen!=0 ) {
        byte resp[16];
        int rc = BlinkM_receiveBytes(addr, resp, recvlen);
        for( int i=0; i<recvlen; i++) 
            Serial.print(resp[i],BYTE);
    }

    for(int i=0; i<30;i++)
        serInStr[i] = 0;  // say we've used the string (not needed really)
    
    digitalWrite(ledPin,LOW); // show we're done
    
}   


//read a string from the serial and store it in an array
//you must supply the str array variable
//returns number of bytes read, or zero if fail
uint8_t readCommand(byte *str)
{
    uint8_t b,i;
    if( ! Serial.available() ) return 0;  // wait for serial

    b = Serial.read();
    if( b != CMD_START_BYTE )         // check to see we're at the start
        return 0;
#ifdef DEBUG
    Serial.println("startbyte");
#endif

    str[0] = b;
    i = 100;
    while( Serial.available() < 3 ) {   // wait for the rest
        delay(1); 
        if( i-- == 0 ) return 0;        // get out if takes too long
    }
    for( i=1; i<4; i++)
        str[i] = Serial.read();       // fill it up
#ifdef DEBUG
    Serial.println("header");
#endif

    uint8_t sendlen = str[2];
#ifdef DEBUG
    Serial.print("cmdlen:");  Serial.println( sendlen, DEC);
#endif
    if( sendlen == 0 ) return 0;
    i = 100;
    while( Serial.available() < sendlen ) {  // wait for the final part
        delay(1); if( i-- == 0 ) return 0;
    }
    for( i=4; i<4+sendlen; i++ ) 
        str[i] = Serial.read();       // fill it up

#ifdef DEBUG
    Serial.println("got all");
#endif
    return 4+sendlen;
}

tbc

Which is connected to this code

/*
 * BlinkM_funcs.h -- Arduino 'library' to control BlinkM
 * --------------
 *
 *
 * Note: original version of this file lives with the BlinkMTester sketch
 *
 * Note: all the functions are declared 'static' because 
 *       it saves about 1.5 kbyte in code space in final compiled sketch.  
 *       A C++ library of this costs a 1kB more.
 *
 * 2007-8, Tod E. Kurt, ThingM, http://thingm.com/
 *
 * version: 20081101
 *
 * history:
 *  20080101 - initial release
 *  20080203 - added setStartupParam(), bugfix receiveBytes() from Dan Julio
 *  20081101 - fixed to work with Arduino-0012, added MaxM commands,
 *             added test script read/write functions, cleaned up some functions
 *
 */

#include "WProgram.h"
#include "wiring.h"
#include "Wire.h"

// format of light script lines: duration, command, arg1,arg2,arg3
typedef struct _blinkm_script_line {
  uint8_t dur;
  uint8_t cmd[4];    // cmd,arg1,arg2,arg3
} blinkm_script_line;


// Call this first (when powering BlinkM from a power supply)
static void BlinkM_begin()
{
  Wire.begin();                // join i2c bus (address optional for master)
}

// General version of BlinkM_beginWithPower().
// Call this first when BlinkM is plugged directly into Arduino
// FIXME: make this more Arduino-like
static void BlinkM_beginWithPowerPins(byte pwrpin, byte gndpin)
{
  DDRC |= _BV(pwrpin) | _BV(gndpin);  // make outputs
  PORTC &=~ _BV(gndpin);
  PORTC |=  _BV(pwrpin);

  delay(100);  // wait for things to stabilize

  Wire.begin();
}

// Call this first when BlinkM is plugged directly into Arduino
// FIXME: make this more Arduino-like
static void BlinkM_beginWithPower()
{
  BlinkM_beginWithPowerPins( PORTC3, PORTC2 );
}

// sends a generic command
static void BlinkM_sendCmd(byte addr, byte* cmd, int cmdlen)
{
  Wire.beginTransmission(addr);
  for( byte i=0; i<cmdlen; i++) 
    Wire.send(cmd[i]);
  Wire.endTransmission();
}

// receives generic data
// returns 0 on success, and -1 if no data available
// note: responsiblity of caller to know how many bytes to expect
static int BlinkM_receiveBytes(byte addr, byte* resp, byte len)
{
  Wire.requestFrom(addr, len);
  if( Wire.available() ) {
    for( int i=0; i<len; i++) 
      resp[i] = Wire.receive();
    return 0;
  }
  return -1;
}

// Sets the I2C address of the BlinkM.  
// Uses "general call" broadcast address
static void BlinkM_setAddress(byte newaddress)
{
  Wire.beginTransmission(0x00);  // general call (broadcast address)
  Wire.send('A');
  Wire.send(newaddress);
  Wire.send(0xD0);
  Wire.send(0x0D);  // dood!
  Wire.send(newaddress);
  Wire.endTransmission();
  delay(50); // just in case
}


// Gets the I2C address of the BlinKM
// Kind of redundant when sent to a specific address
// but uses to verify BlinkM communication
static int BlinkM_getAddress(byte addr)
{
  Wire.beginTransmission(addr);
  Wire.send('a');
  Wire.endTransmission();
  Wire.requestFrom(addr, (byte)1);  // general call
  if( Wire.available() ) {
    byte b = Wire.receive();
    return b;
  }
  return -1;
}

// Gets the BlinkM firmware version
static int BlinkM_getVersion(byte addr)
{
  Wire.beginTransmission(addr);
  Wire.send('Z');
  Wire.endTransmission();
  Wire.requestFrom(addr, (byte)2);
  if( Wire.available() ) {
    byte major_ver = Wire.receive();
    byte minor_ver = Wire.receive();
    return (major_ver<<8) + minor_ver;
  }
  return -1;
}

// Demonstrates how to verify you're talking to a BlinkM 
// and that you know its address
static int BlinkM_checkAddress(byte addr)
{
  //Serial.print("Checking BlinkM address...");
  int b = BlinkM_getAddress(addr);
  if( b==-1 ) {
    //Serial.println("No response, that's not good");
    return -1;  // no response
  } 
  //Serial.print("received addr: 0x");
  //Serial.print(b,HEX);
  if( b != addr )
    return 1; // error, addr mismatch 
  else 
    return 0; // match, everything okay
}

// Sets the speed of fading between colors.  
// Higher numbers means faster fading, 255 == instantaneous fading
static void BlinkM_setFadeSpeed(byte addr, byte fadespeed)
{
  Wire.beginTransmission(addr);
  Wire.send('f');
  Wire.send(fadespeed);
  Wire.endTransmission();  
}

// Sets the light script playback time adjust
// The timeadj argument is signed, and is an additive value to all
// durations in a light script. Set to zero to turn off time adjust.
static void BlinkM_setTimeAdj(byte addr, byte timeadj)
{
  Wire.beginTransmission(addr);
  Wire.send('t');
  Wire.send(timeadj);
  Wire.endTransmission();  
}

// Fades to an RGB color
static void BlinkM_fadeToRGB(byte addr, byte red, byte grn, byte blu)
{
  Wire.beginTransmission(addr);
  Wire.send('c');
  Wire.send(red);
  Wire.send(grn);
  Wire.send(blu);
  Wire.endTransmission();
}

// Fades to an HSB color
static void BlinkM_fadeToHSB(byte addr, byte hue, byte saturation, byte brightness)
{
  Wire.beginTransmission(addr);
  Wire.send('h');
  Wire.send(hue);
  Wire.send(saturation);
  Wire.send(brightness);
  Wire.endTransmission();
}

// Sets an RGB color immediately
static void BlinkM_setRGB(byte addr, byte red, byte grn, byte blu)
{
  Wire.beginTransmission(addr);
  Wire.send('n');
  Wire.send(red);
  Wire.send(grn);
  Wire.send(blu);
  Wire.endTransmission();
}

// Fades to a random RGB color
static void BlinkM_fadeToRandomRGB(byte addr, byte rrnd, byte grnd, byte brnd)
{
  Wire.beginTransmission(addr);
  Wire.send('C');
  Wire.send(rrnd);
  Wire.send(grnd);
  Wire.send(brnd);
  Wire.endTransmission();
}
// Fades to a random HSB color
static void BlinkM_fadeToRandomHSB(byte addr, byte hrnd, byte srnd, byte brnd)
{
  Wire.beginTransmission(addr);
  Wire.send('H');
  Wire.send(hrnd);
  Wire.send(srnd);
  Wire.send(brnd);
  Wire.endTransmission();
}

//
static void BlinkM_getRGBColor(byte addr, byte* r, byte* g, byte* b)
{
  Wire.beginTransmission(addr);
  Wire.send('g');
  Wire.endTransmission();
  Wire.requestFrom(addr, (byte)3);
  if( Wire.available() ) {
    *r = Wire.receive();
    *g = Wire.receive();
    *b = Wire.receive();
  }
}

//
static void BlinkM_playScript(byte addr, byte script_id, byte reps, byte pos)
{
  Wire.beginTransmission(addr);
  Wire.send('p');
  Wire.send(script_id);
  Wire.send(reps);
  Wire.send(pos);
  Wire.endTransmission();
}

//
static void BlinkM_stopScript(byte addr)
{
  Wire.beginTransmission(addr);
  Wire.send('o');
  Wire.endTransmission();
}

//
static void BlinkM_setScriptLengthReps(byte addr, byte script_id, 
                                       byte len, byte reps)
{
  Wire.beginTransmission(addr);
  Wire.send('L');
  Wire.send(script_id);
  Wire.send(len);
  Wire.send(reps);
  Wire.endTransmission();
}

// Fill up script_line with data from a script line
// currently only script_id = 0 works (eeprom script)
static void BlinkM_readScriptLine(byte addr, byte script_id, 
                                  byte pos, blinkm_script_line* script_line)
{
  Wire.beginTransmission(addr);
  Wire.send('R');
  Wire.send(script_id);
  Wire.send(pos);
  Wire.endTransmission();
  Wire.requestFrom(addr, (byte)5);
  while( Wire.available() < 5 ) ; // FIXME: wait until we get 7 bytes
  script_line->dur    = Wire.receive();
  script_line->cmd[0] = Wire.receive();
  script_line->cmd[1] = Wire.receive();
  script_line->cmd[2] = Wire.receive();
  script_line->cmd[3] = Wire.receive();
}

//
static void BlinkM_writeScriptLine(byte addr, byte script_id, 
                                   byte pos, byte dur,
                                   byte cmd, byte arg1, byte arg2, byte arg3)
{
#ifdef BLINKM_FUNCS_DEBUG
  Serial.print("writing line:");  Serial.print(pos,DEC);
  Serial.print(" with cmd:"); Serial.print(cmd); 
  Serial.print(" arg1:"); Serial.println(arg1,HEX);
#endif
  Wire.beginTransmission(addr);
  Wire.send('W');
  Wire.send(script_id);
  Wire.send(pos);
  Wire.send(dur);
  Wire.send(cmd);
  Wire.send(arg1);
  Wire.send(arg2);
  Wire.send(arg3);
  Wire.endTransmission();
}

tcb

//
static void BlinkM_writeScript(byte addr, byte script_id, 
                               byte len, byte reps,
                               blinkm_script_line* lines)
{
#ifdef BLINKM_FUNCS_DEBUG
  Serial.print("writing script to addr:"); Serial.print(addr,DEC);
  Serial.print(", script_id:"); Serial.println(script_id,DEC);
#endif
  for(byte i=0; i < len; i++) {
    blinkm_script_line l = lines[i];
    BlinkM_writeScriptLine( addr, script_id, i, l.dur,
                            l.cmd[0], l.cmd[1], l.cmd[2], l.cmd[3]);
  }
  BlinkM_setScriptLengthReps(addr, script_id, len, reps);
}

//
static void BlinkM_setStartupParams(byte addr, byte mode, byte script_id,
                                    byte reps, byte fadespeed, byte timeadj)
{
  Wire.beginTransmission(addr);
  Wire.send('B');
  Wire.send(mode);
  Wire.send(script_id);
  Wire.send(reps);
  Wire.send(fadespeed);
  Wire.send(timeadj);
  Wire.endTransmission();
} 


// Gets digital inputs of the BlinkM
// returns -1 on failure
static int BlinkM_getInputsO(byte addr)
{
  Wire.beginTransmission(addr);
  Wire.send('i');
  Wire.endTransmission();
  Wire.requestFrom(addr, (byte)1);
  if( Wire.available() ) {
    byte b = Wire.receive();
    return b; 
  }
  return -1;
}

// Gets digital inputs of the BlinkM
// stores them in passed in array
// returns -1 on failure
static int BlinkM_getInputs(byte addr, byte inputs[])
{
  Wire.beginTransmission(addr);
  Wire.send('i');
  Wire.endTransmission();
  Wire.requestFrom(addr, (byte)4);
  while( Wire.available() < 4 ) ; // FIXME: wait until we get 4 bytes
    
  inputs[0] = Wire.receive();
  inputs[1] = Wire.receive();
  inputs[2] = Wire.receive();
  inputs[3] = Wire.receive();

  return 0;
}

Sorry this could be asking too much, dont worry I am trying to look at other ways round it too.

I think thats one of the main reasons I cant get my head round it.

Thanks

After a quick peek at the two programs I got the impression, that both are reading data from the serial line. Just in the setup() function you have:

Firmata.begin(57600);

...

Serial.begin(19200);

So at what speed is your serial port going to work? 57600 or 19200? And even if you sort that out, what program is listening on the other side of the line and will it handle the data sent by you two pieces of program correctly?

If you want to use Firmata, better write a callback for your BlinkM led and let Firmata handle serial port alone.

Korman

yeah I spotted that after I uploaded the post, I changed them both to 19200 and this made it so the LED was able to be controlled. But I only got a random reading from the analogue input even when a I/R sensor is connected and giving off a voltage.

Im using Max MSP to read all the analogue in's and send and RGB colour to the LED.

How would I right a callback? I know what you mean, so only one part of the code is controlling the serial port just not too sure how to do it.

Thanks