Pages: [1]   Go Down
Author Topic: BlinkM program help!  (Read 466 times)
0 Members and 1 Guest are viewing this topic.
Offline Offline
Sr. Member
****
Karma: 1
Posts: 284
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

I'm filling in array serBufLen[32] by using the serial monitor.  To fill the array with relevant information I first need to know what format to type this info into the serial monitor? Do I just copy and paste the entire set and press send?  E.g. {0x01,0x09,0x01,0x01, 'g'}
                                           start|blinkM|bytes|bytes| command
                                           byte|device|send |receive|

Also, what am I doing by changing values of num_bytes_to_send, num_bytes_to_receive, send_byte0??  What do the commands 'g', 'f', 'W' mean for send_byte0? smiley-small

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
 *
 *
 * 2007-11, Tod E. Kurt, ThingM, http://thingm.com/
 *
 */

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

//#define DEBUG 1

// set this if you're plugging a BlinkM directly into an Arduino,
// into the standard position on analog in pins A2,A3 (power) A4,A5 (i2c)
// otherwise you can set it to false or just leave it alone
const boolean BLINKM_ARDUINO_POWERED = false;

const int CMD_START_BYTE = 0x01;

//int blinkm_addr = 0x09;
int blinkm_addr;

const int serBufLen = 32;

// array that will hold the serial input string
byte serInBuf[serBufLen];

int ledPin = 13;

//*********************************************************************

void setup()
{
  // initialize serial communication:
  Serial.begin(9600);
  Serial.println();
  Serial.println("BlinkMCommunicator starting up...");
  delay(2000);

  //identify pin13 as an output
  pinMode(ledPin, OUTPUT);
 
  //if powered on using pins A2,A3 for power
  if(BLINKM_ARDUINO_POWERED)
  {
    //library function
    BlinkM_beginWithPower();
  }
  else
  {
    //library function to call wire.begin()
    BlinkM_begin();
    Serial.println("Wire library has begun.");
  }
  delay(1000);  // wait for power to stabilize

  //1. Look for BlinkM led on I2C line if
  //blinkm_addr is not identified in the beginning
  lookForBlinkM();

/*
  //library function
  byte rc = BlinkM_checkAddress(blinkm_addr);
 
  if( rc == -1 )
  {
    Serial.println("No response");  // FIXME: make this an interogator loop?
    delay(2000);
  }
  else if( rc == 1 )
  {
    Serial.println("I2C address mismatch");
    delay(2000);
  }
  else   
  {
    Serial.println("BlinkMCommunicator ready");
    delay(2000);
  }
*/

#ifdef DEBUG
  Serial.println("DEBUG MODE: will not allow proper functionality");
#endif
}


//*******************************************************************

void loop()
{
  int num;

  //2. Read the serial port and create a string out of what you read
  num = readCommand(serInBuf);
  Serial.println(num);
  delay(2000);
   
  if(num == 0)   // see if we got a proper command string yet
    return; //go to end of loop(){}
 
  digitalWrite(ledPin,HIGH);  // say we're working on it
  //delay(2000);

  byte addr    = serInBuf[1];
  byte sendlen = serInBuf[2];
  byte recvlen = serInBuf[3];
  byte* cmd    = serInBuf+4;

  if(addr == 128)
  {
    //3. i2cScanResult called when address is found in BlinkM_scanI2CBus()
    //128 == i2c scan command
    BlinkM_scanI2CBus(cmd[0], cmd[1], i2cScanResult);
    Serial.write(128);
  }
  else
  {
    // normal transaction
#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.write(resp[i]);
        }
    }
   
    for(int i=0; i < serBufLen; i++)
    {
        serInBuf[i] = 0;  // say we've used the string (not needed really)
    }

  } // normal transaction
  digitalWrite(ledPin,LOW); // show we're done   
}
//************************************************************

//1. Look for BlinkM led on I2C line
void lookForBlinkM()
{
  Serial.print("Looking for a BlinkM: ");
 
  //library function
  int a = BlinkM_findFirstI2CDevice();
 
  if( a == -1 )
  {
    Serial.println("No I2C devices found");
  }
  else
  {
    Serial.print("Device found at addr ");
    Serial.println(a, DEC);
    blinkm_addr = a;
  }
}

//2. 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;
  uint8_t i;
 
  if(!Serial.available())
  {
    return 0;  // wait for serial
  }
 
  b = Serial.read();
 
  if(b != CMD_START_BYTE)
  { 
    return 1;  // check to see we're at the start
  }
 
#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;
}

//3. Called when address is found in BlinkM_scanI2CBus()
void i2cScanResult( byte addr, byte result )
{
    Serial.write(addr);
    Serial.write(result);
}
Logged

peace*&^

Seattle, WA USA
Online Online
Brattain Member
*****
Karma: 642
Posts: 50432
Seattle, WA USA
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Code:
  if(!Serial.available())
  {
    return 0;  // wait for serial
  }
No, it does not.

Code:
  if(b != CMD_START_BYTE)
  { 
    return 1;  // check to see we're at the start
  }
You can't send 0x01 to the Arduino using the Serial Monitor. So, I stopped reading here.
Logged

Offline Offline
Sr. Member
****
Karma: 1
Posts: 284
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Yes, thanks. That is where I was getting stuck.  This is the example code from thingm.com/products/blinkm.html .  I put the original code below before I started testing with it.  I guess "return 0" brings you back to the start of the loop()?  The comment in the project description says to enter a set of bytes.  If I can't enter 0x01 in the serial monitor which makes the condition "if( b != CMD_START_BYTE )" false, then I'm not sure what the programmer was thinking.  Maybe I should just change from hex to decimal.

Code:
//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;
« Last Edit: January 26, 2013, 09:38:47 am by encryptor » Logged

peace*&^

Seattle, WA USA
Online Online
Brattain Member
*****
Karma: 642
Posts: 50432
Seattle, WA USA
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Quote
Maybe I should just change from hex to decimal.
Won't make a bit of difference. 0x01 == 01 == 0b00000001 = 1. None of which you can send from the Serial Monitor.

That code is not designed to work with the Serial Monitor, which can't send binary data. It IS designed to work with an application that CAN send binary data.
Logged

Offline Offline
Sr. Member
****
Karma: 1
Posts: 284
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

With that information I downloaded RealTerm and set my serial port and baud rate under the Port tab.  Then I go under I2C tab sent the startbyte 01, blimkM device address 09, send 01, receive 01 using Byte button, and finally g using Ascii button.  All goes into Write box and it looks like I'm sending info thru the port, but I'm not sure what should happen?


* blinkMCommunicator_help.png (178.74 KB, 845x504 - viewed 10 times.)
« Last Edit: January 26, 2013, 11:00:06 am by encryptor » Logged

peace*&^

Offline Offline
Sr. Member
****
Karma: 1
Posts: 284
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Ah ok I've made some progress.  I'm suppose to use the program BlinkM Sequencer to control the colors over serial cable, which I've now done.  However I want to control colors wirelessly using my BT module.  I've attached the following code at my greatest attempt in doing so.  The program work via the A-B cable, but when I switch over to BT port (com5) and connect to that in BlinkM Sequencer the colors don't play and instead I get a default color script playing.  BlinkM Sequencer shows it is connected.  The BT module also shows to be connected, so I don't know where to go from here. smiley-zipper

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
 *
 *
 * 2007-11, Tod E. Kurt, ThingM, http://thingm.com/
 *
 */

#include <SoftwareSerial.h>
#include "Wire.h"
#include "BlinkM_funcs.h"

//#define DEBUG 1

// set this if you're plugging a BlinkM directly into an Arduino,
// into the standard position on analog in pins 2,3,4,5
// otherwise you can set it to false or just leave it alone
const boolean BLINKM_ARDUINO_POWERED = true;

const int CMD_START_BYTE = 0x01;

//int blinkm_addr = 0x09;

const int serBufLen = 32;
byte serInBuf[serBufLen];  // array that will hold the serial input string

int ledPin = 12;
int bluetoothTx = 1;
int bluetoothRx = 0;

SoftwareSerial bluetooth(bluetoothTx, bluetoothRx);


void setup()
{
  Serial.begin(19200);
  bluetooth.begin(115200);
  delay(100);
  Serial.println("BlinkMCommunicator starting up...");

  pinMode(ledPin, OUTPUT);
  if( BLINKM_ARDUINO_POWERED ) {
    BlinkM_beginWithPower();
  }
  else {
    BlinkM_begin();
  }
  delay(100);  // wait for power to stabilize

  lookForBlinkM();

  /* 
  byte rc = BlinkM_checkAddress( blinkm_addr );
  if( rc == -1 )
    Serial.println("No response");  // FIXME: make this an interogator loop?
  else if( rc == 1 )
    Serial.println("I2C address mismatch");
  */

  Serial.println("BlinkMCommunicator ready");
#ifdef DEBUG
  Serial.println("DEBUG MODE: will not allow proper functionality");
#endif
}

void lookForBlinkM()
{
  Serial.print("Looking for a BlinkM: ");
  int a = BlinkM_findFirstI2CDevice();
  if( a == -1 ) {
    Serial.println("No I2C devices found");
  } else {
    Serial.print("Device found at addr ");
    Serial.println( a, DEC);
    //blinkm_addr = a;
  }
}

// called when address is found in BlinkM_scanI2CBus()
void i2cScanResult( byte addr, byte result )
{
    Serial.write(addr);
    Serial.write(result);
}

void loop()
{
  int num;
  //read the serial port and create a string out of what you read
  num = readCommand(serInBuf);
  if( num == 0 )   // see if we got a proper command string yet
    return;
 
  digitalWrite(ledPin,HIGH);  // say we're working on it

    byte addr    = serInBuf[1];
    byte sendlen = serInBuf[2];
    byte recvlen = serInBuf[3];
    byte* cmd    = serInBuf+4;

  if( addr == 128 ) { // 128 == i2c scan command
    BlinkM_scanI2CBus( cmd[0], cmd[1], i2cScanResult);
    Serial.write(128);
  }
  else { // normal transaction
   
#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.write(resp[i]);
    }
   
    for(int i=0; i< serBufLen; i++) {
        serInBuf[i] = 0;  // say we've used the string (not needed really)
    }

  } // normal transaction

  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;
}

Logged

peace*&^

Seattle, WA USA
Online Online
Brattain Member
*****
Karma: 642
Posts: 50432
Seattle, WA USA
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Since your current problem no longer is related to the BlinkM module and programming it, but is now related to using bluetooth, you need to start a new thread.
Logged

Pages: [1]   Go Up
Jump to: