Communication between arduinos with sensors

Hi guys!!

I have a project that I would like to develop but I am missing some things, specially related with serial communication.

I have read tons of forums but as much I read, more confused I get about it. I am sorry if I am repeating this question.

What I want to do is very simple to understand and to code too, I think... I know it is a quite simple method but I have realised which is the most reliable way to do it.

we start by having 2 arduinos connected via serial, the (lets call) Arduino 1 has 4 pots and 4 switches, it read the pots and switches values, pack it into a group of information like "255,255,255,255,1,1,1,1" (this would be the max values of each one of the sensors) and send this pack to the serial.....
..... now the Arduino 2 receives this pack, decode it to get the separate values and send the pot values (0 to 255) to dim some leds and the switches informations (0 to 1) to control some relays.

So, can somebody suggest me some kind of working code sample or something more clear on how to do it instead of sending me to another topic where I have been before?

Please, try to avoid abstract answers because I am new on this and I am not familiar as I would like to be about arduino coding.

Thank you

Regards

Start by using SoftwareSerial on both Arduinos assuming that the boards do not have 2 or more hardware serial ports. That will enable you to use the hardware serials on the Arduinos to debug your code. Connect the 2 Arduinos together using the pins defined in their SoftwareSerial setups.

Now, forget your eventual aim. Can you send a single, hard code byte from Arduino A to Arduino B, read it and display it ? When you can do that you are ready to move on.

Hi,

I do have some communication going on...

in the arduino 1 I have this code

void loop() {
  
  PanVal = analogRead(Pan);
  PanOUT = map(PanVal, 0, 1022, 0, 255);
  
  Serial.println(PanOUT);
   delay(2);

  
  }

this is sending the mapped pod values over the serial to the arduino 2 which code is this one:

byte byteRead;
const int analogOutPin = 9;

float sensorValue = 0;
float outputValue = 0;

void setup() {                
// Turn the Serial Protocol ON
  Serial.begin(9600);
}

void loop() {
   /*  check if data has been sent from the computer: */
  if (Serial.available()) {
    
    /* read the most recent byte */
    byteRead = Serial.read();
    
    sensorValue = analogRead(byteRead);            
    analogWrite(analogOutPin, byteRead);
    Serial.write(byteRead);
    
  }
}

As I have read in other posts, what I am getting are ASCII through the serial and, I don't know the way to "translate" this ASCII to numeric and keep the value of 0-255 for the pot value in the receiving arduino... I can see the good numbers in the Serial Monitor because I am using the "Serial.write" but, as everybody knows, if I change it to Serial.print I will get the values that are really being sent to the led output which are number like 13, 10, 49, 53 and so on (ASCII)....

This is just one of the problems I have, but at least I have communication between the 2 boards and monitoring for debugging, now we can go straight to the working code, please...

The other problem for which I need a solution is on how to pack all the data on the outgoing arduino and unpack and interpret that pack of information on the receiving arduino in order to put the leds and the relays to work.

Thanks

How are the 2 Arduinos connected at the moment ?

You don't need to pack the data on the sending Arduino beyond adding a "start of message" indicator, a dividing character between each value and an "end of message" indicator at the end of the message. Most of the work then takes place on the receiving Arduino. This will be a good place to start in order to build a string on the receiving Arduino that you can then take apart using the strtok() function using the dividing characters that you added before transmission. Gammon Forum : Electronics : Microprocessors : How to process incoming serial data without blocking

Is it a good idea to use the same serial interface for receiving data and writing to the serial output ?

Right now, the arduino are directly wired (Arduino 1 tx to arduino 2 rx) but the goal will be the use of uart radios like xbee or whatever...

I will take look on your link

thank you

Yes, you are right, I have managed to "print" all the values arranged on the way I need, as I have written before, like 122,203,68,0,1,1,0,1 (pot,pot,pot,pot,sw,sw,sw,sw), now, as you said, the hard work is to get this pack and apply the right value AS A NUMBER into its respective output.... Thats where I am and I am facing some difficulties to go over it.

I have seen your link very fast and, as it is a complete code, I am not understanding where and what is doing the function you mentioned. I don't deal with arduinos on a daily base.... sorry

I recently had success with a master and slave arduino. The master sends a "*" as a data request and the slave then sends data back:

Master code:

String readString; //make global.
uint8_t valueA, valueB;
void setup() {
  Serial.begin(19200);
}

void loop() {
  Serial.println(F("*"));
  delay (1000);
}

void serialEvent(){ //is called any time serial data is available
  while(Serial.available()){
    char c = Serial.read();
    readString += c;
   
    if (c == "*") {
      uint8_t = readString.indexOf('a'); //gets position of "a".
      uint8_t = readString.indexOf('b'):

      String firstString = readString.substring(0, a); //makes a new string called "firstString" and stores all the characters from position 0 to a.
      valueA = firstString.toInt(); //converts to int.
      String secondString = readString.substring(a + 1, b) //makes a new string called "secondString and stores all the numbers from a + 1 to b.
      valueB = secondString.toInt();
      readString = ""; //clears string once all data recieved and decoded.
}

Slave code:

uint8_t valueA, valueB;

void setup() {
 Serial.begin(19200); //MUST be same baud rate.
}

void loop() {
  valueA = analogRead(0) / 4; //keep within 0-255
  delay(10); //needed between analog readings
  valueB = analogRead(1) / 4;
  delay(10);
}

void serialEvent() {
  char c = Serial.read();
  switch (c) {
    case '*': //all data requested
    Serial.print(valueA);
    Serial.print("a");
    Serial.print(valueB);
    Serial.print("b");
    Serial.println("*"); //end of string.
    break;

    case 'a': //a single character command from master
    //do something.
    break;
  }
}

The master sends a data request every second. The slave, which is just doing its thing until a command is recieved, sends its data back as a string with markers indicating the end of a value if the command is "*". If you send it an "a", it will do something else then continue back to the main loop doing its thing. The master then decodes the string by finding the position of each data marker and converts the characters to a new string, then converts that string to an integer.

Great example, this one I can understand clearly, let me reach my computer to try it out.

Thank you very much

Cheers

Hi, well, I got my hands on the arduino but something on the "Master" side is not working and I am not realising what (lack of experience coding), sorry...

This is the "Slave" code which is working;

int pot1;
int pot2;

void setup() {
 Serial.begin(9600); //MUST be same baud rate.
}

void loop() {
  pot1 = analogRead(0) / 4; //keep within 0-255
  delay(5); //needed between analog readings
  pot2 = analogRead(1) / 4;
  delay(5);
  
  serialEvent();
}

void serialEvent() {
 // char c = Serial.read();
 // switch (c) {
 //   case '*': //all data requested
    Serial.print("a");
    Serial.print(pot1);
    Serial.print("b");
    Serial.print(pot2);
    Serial.println("*"); //end of string.
  //  break;

  //  case 'a': //a single character command from master
    //do something.
  //  break;
 // }
}

This is the "Master" code and I am having an issue to compile:

String readString; //make global.
int a;
int b;
int pot1;
int pot2;
String Pots[] = {"a", "b"};


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

void loop() {
  Serial.println(F(","));
  delay (10);
  
  if(Serial.available()) {
    // char c = Serial.read();
    // readString += c;
    // if (c == '*') {
      Pots = readString.indexOf("a"); //gets position of "a".
      Pots = readString.indexOf("b");

      String firstString = readString.substring(0, a); //makes a new string called "firstString" and stores all the characters from position 0 to a.
      pot1 = firstString.toInt(); //converts to int.
      String secondString = readString.substring(a + 1, b); //makes a new string called "secondString and stores all the numbers from a + 1 to b.
      pot2 = secondString.toInt();
      readString = ""; //clears string once all data recieved and decoded.
      Serial.print(",");
      //}
      
      analogWrite(9, pot1);
      analogWrite(10, pot2);
    }
  
  
}

Any sugestion OR, can someone repair it for me?

thank you in advance..

Cheers

There are a lot of reasons its not working. You have a lot of code commented out and in the wrong places. Try uploading the code exactly how I wrote it and see if it works that way.

serialEvent() should NOT be in the main loop. It gets called automatically when ever there is serial data available. You should have the slave wait until data is requested before sending data back.

Hi,

| have done it as you have suggested and I got this error:

Oops!
That should be:

uint8_t a = readString.indexOf('a'); //gets position of "a".
uint8_t b = readString.indexOf('b'):

I just forgot to put a names of the variables there.

Thank you Vulture, it is working now... very nice job man....

I have cut the delays on the slave analog readings and reduced the delay on the Master to 10ms and now I have a real time dimmers

just one question... how can I rename this with my own names?
uint8_t valueA, valueB;

Thank you again for you precious help

Cheers

just one question... how can I rename this with my own names?
uint8_t valueA, valueB;

Use any text editor, including the IDE, and start typing.

uint8_t is a variable type that goes from 0 to 255. It like "int" but only uses one byte of memory.

You could name the variable any thing you want.

If you need a variable that goes from -127 to 127 use int8_t.

Understood... thats not an issue at all.

I have been testing only with one pot and one led and everything works perfect but, when I attach the second pot and led it doesn't work. It seams that the code is getting the value "a" but not the value "b"...
I have checked the connections several times and are all correct, maybe the code you wrote is not getting the "b" as it should.

Post your sketches exactly as you have them uploaded. Also, are you sure you're using analog inputs 0 and 1?

I haven't changed or add anything to your original code... on it, I presume that "b" is the second channel for a second pot, right?

All the connections are confirmed, the slave arduino is sending the right data "255a255b*", saw it on Serial Monitor.

I bet the issue is that you're sending too many commands over serial by shortening the master code delay. Try increasing that amount to 100 ms or so and see if it works.

Hi Vulture,

I still have the issue even after having increased the time to 1000...

what the second led has been doing from the beginning is that, if the pot2 is under 50% the led2 is off AND if the pot2 is over 50% the led2 turns on.

This must be an error on the "master" code because the "slave" is sending a clear data string, seen on the serial monitor.....

The codes I am using are the original ones... no changes at all on it