Multi-Arduino serial comm. reports 0's

I am stuck trying to get data from one arduino to another. This article on serial communication was extremely helpful, but am currently on receiving 0's. Other attempts had 255 for both high/low bytes.

TL;DR Objective: Master arduino defines an interval (in micros) for Slaves to trigger stepper motors.

Longer Desc.: 1 Master arduino defines 10x slave arduino's "target step interval" (in micros). At various points of time the master sets a new target for each slave, and each slave slowly adjusts its current step-interval to reach its target interval.

NOTE:

  • I have omitted the slave's "speed adjustment" code to focus on the issue above/li]
  • Stepper motor desired step-interval is ~500-520 micros without microstepping (half or quarter of this if microstepping).
  • I chose to transfer by binary as I suspect it may be the fastest. I am concerned time wasted on receiving commands via serial may affect stepper motors accuracy and potentially mis-step/stall
  • Should i be using a different method or 'receiveEvent' / interrupt type approach?

Any help is greatly appreciated. Thanks

MASTER CODE:

/*
 * MASTER SPEED CONTROLL / Test changing Target RPS every X Seconds
 * Need 1 timer, every X ms change RPSmicros by X
 */
#include <Wire.h>

unsigned long prevMillis = 0;
unsigned long intervalMillis = 4000; //how long to trigger send to slaves. 1000=1s
int RPSmicros = 500; //motor target speed (no microsteps)

void setup() {
  Wire.begin(8);                // join i2c bus with address #8
  Serial.begin(9600);
}

void loop() {
unsigned long curMillis = millis();

if (curMillis - prevMillis >= intervalMillis) {
  prevMillis = curMillis;
//  RPSmicros += 10;
  
  Wire.beginTransmission(8); // transmit to device #8
  Wire.write('*'); //attempt at writing a flag for start
  Wire.write(highByte(RPSmicros)); //send remainder
  Wire.write(lowByte(RPSmicros)); 
  Wire.endTransmission();    // stop transmitting  
  Serial.println('*');
  Serial.println(highByte(RPSmicros));
  Serial.println(lowByte(RPSmicros));

//  intValue = RPSmicros; 
  }
  else {
//  prevMillis = curMillis;
  }
}

SLAVE CODE:

#include <Wire.h>
int RPSmicros;
byte b[2]; // byte array

void setup() {
  Wire.begin(8);                // join i2c bus with address #8
//  Wire.onReceive(receiveEvent); // register event
  Serial.begin(9600);           // start serial for output
}

void loop() {
memset(b, '\0', 2);

if (Serial.available() > 0) { // only loop the serial structure if its serialing
  char inbyte = '\0';         // null? 
  inbyte = Serial.read();     // change the inbyte to the waiting byte

  if (inbyte == '*') {        // this means its the start of a number
    for (int i=0; i<2; i++) {
        b[i] = Serial.read();
    }
  }
}
  RPSmicros = b[0] * 256 + b[1];
  Serial.println(b[0]);
  Serial.println(b[1]);
  Serial.println(RPSmicros);
  Serial.println();
}

//void receiveEvent(int howMany) {
//  while (1 < Wire.available()) { // loop through all but the last
//    char c = Wire.read(); // receive byte as a character
//    Serial.print(c);         // print the character
//  }
//  byte b[0] = Serial.read();
//  byte b[1] = Serial.read();
//  RPSmicros = b[0] * 256 + b[1]; 
//  Serial.println(b1);
//  Serial.println(b2);
//  Serial.println();
//  x = Wire.read();    // receive byte 
//}

Are you sending the data using Serial or I2C?

...R

Thank you for taking the time to reply. I believe I2C. Now that you've asked there is a glaring issue ask may be crossing methods. The A4 A5 pins and ground are connected.

Which would you recommend based on the timing details above?

Your slave code has a problem. If one byte has arrived (Serial.avaliable() > 0) and that byte is a '*', read two more bytes that might not have arrived yet.

Remember, serial is slow compared to the processor.

@OP

You have mixed up I2C Serial Communication with UART Serial Communication. From your codes, it appears that you are using I2C Bus for data exchange between two Arduinos. Please, revise your hardware connection and software routines as per following recommendations and report the results.

A: I2C Bus connection between 2 Arduinos
i2cmsunonano.png

B: Master Codes:

#include <Wire.h>

unsigned long prevMillis = 0;
unsigned long intervalMillis = 4000; //how long to trigger send to slaves. 1000=1s
int RPSmicros = 500; //0x01F4 motor target speed (no microsteps)

void setup()
{
  Wire.begin();//begin(8);                // join i2c bus with address #8
  Serial.begin(9600);
}

void loop()
{
  //unsigned long curMillis = millis();

  if (millis() - prevMillis >= intervalMillis)
  {
    prevMillis = millis(); //curMillis;
    //  RPSmicros += 10;

    Wire.beginTransmission(8); // transmit to device #8
    Wire.write('*'); //attempt at writing a flag for start
    Wire.write(highByte(RPSmicros)); //send remainder
    Wire.write(lowByte(RPSmicros));
    Wire.endTransmission();    // stop transmitting

    Serial.println('*');
    Serial.println(highByte(RPSmicros), HEX); //0x01; upper byte of 500
    Serial.println(lowByte(RPSmicros), HEX); //0xF4; lower byte of 500
  }
}

C: Slave Codes:

#include <Wire.h>
int RPSmicros;
byte b[3];//b[2]; // byte array
bool flag1 = LOW;

void setup()
{
  Wire.begin(8);                // join i2c bus with address #8
  Wire.onReceive(receiveEvent); // register event
  Serial.begin(9600);           // start serial for output
}

void loop()
{
  if (flag1 == HIGH)
  {
    if (b[0] == '*')
    {
      // RPSmicros = b[0] * 256 + b[1];
      Serial.println(b[0]); //shows: *
      Serial.println(b[1], HEX); //show 0x01; upper byte of 500
      Serial.println(b[2], HEX); //shows: 0xF4; lower byte of 500
      RPSmicros = (b[1] << 8) | b[2];
      Serial.println(RPSmicros, DEC);//shows: 500
      flag1 = LOW;
    }
  }
}

void receiveEvent(int howMany)
{
  for (int i = 0; i < howMany; i++)
  {
    b[i] = Wire.read();
  }
  flag1 = HIGH;
}

D: Slave Serial Monitor
scr-7.png

i2cmsunonano.png

scr-7.png

Thanks so much! This is great.
I haven't seen bitshifts before. Is there a reason why you chose it over "b[1] * 256 + b[2]"?

Any input on whether I should be using this method given the slave's responsibility of driving stepper motors at 250-500 micros per step? I'm going to start testing now, but want to ensure I don't miss steps and stall a motor.

jingleby:
Thanks so much! This is great.
1. I haven't seen bitshifts before. Is there a reason why you chose it over "b[1] * 256 + b[2]"?

2. Any input on whether I should be using this method given the slave's responsibility of driving stepper motors at 250-500 micros per step? I'm going to start testing now, but want to ensure I don't miss steps and stall a motor.

1. b[1] = 0x01 and [b2] = 0xF4
==> 0x01*256 + 0xF4 (0x100 + 0xF4 ----> 0x01F4)
==> 256 + 244
==> 500

The hand calculation gives the same value. Shifting-left by 8-bit is same as multiplying by 256. Both of them would give the same result.

2. Try and see what happens. You can always make safe trails-and errors. safe tells us to remain careful so that nothing is broken and burnt-up!

Thanks for breaking that out :slight_smile:
I intended to ask whether there was a higher likeliness of having pulse accuracy issues with one method of communication over another (i2c/serial/etc). No need to reply, I'm quite pleased the code is working.