Iam trying to design a serial communication system. In this circuit I want to control two LEDs (green and red) via two pots, but actually the circuit doesn’t work. I was adding the circuit, using RS232 shield with dp9 cable to link the two Arduinos. For a better understanding of my problem I was adding the code.
I thought the problem is:
The transmitter Arduino doesn’t send the value, or
You don't need any shield to use serial communication between two Arduinos. I assume you are NOT using two Megas - which would be easier. With two Unos just use SoftwareSerial to create a second Serial port on each of them and connect the SoftwareSerial Rx andTx pins (in both directions) and GND.
Use one of the examples in serial input basics to receive the data and make the transmission of the data compatible.
I've used the below simple serial test code to communicate between two arduinos.
//zoomkat 3-5-12 simple delimited ',' string tx/rx
//from serial port input (via serial monitor)
//and print result out serial port
//Connect the sending arduino rx pin to the receiving arduino rx pin.
//Connect the arduino grounds together.
//What is sent to the tx arduino is received on the rx arduino.
//Open serial monitor on both arduinos to test
//A diode between the slave tx and master rx is suggested
//for isolation, with diode band attached to slave tx side.
//
String readString;
void setup() {
Serial.begin(9600);
Serial.println("serial delimit test 1.0"); // so I can keep track of what is loaded
}
void loop() {
//expect a string like wer,qwe rty,123 456,hyre kjhg,
//or like hello world,who are you?,bye!,
if (Serial.available()) {
char c = Serial.read(); //gets one byte from serial buffer
if (c == ',') {
if (readString.length() >0) {
Serial.print(readString); //prints string to serial port out
Serial.println(','); //prints delimiting ","
//do stuff with the captured readString
readString=""; //clears variable for new input
}
}
else {
readString += c; //makes the string readString
}
}
}
I use for the receiver Arduino the code from Reply #23 in the Thread from Robin2 to receiving the Datas: serial input basics
(I didn't know that the Programming for serial communication is so difficult)
Now I extend the code to control the LED.
The Arduino receive XRed and XGreen value in this form like:
“XRed = 10” , “XGreen = 4”
How can I integrate the values in this Loop?
Void LED ()
{
int VoltR = 25.5 * XRed; //10volt *25.5 = 255
analogWrite(RedledPin, VoltR);
int VoltG = 25.5 * XGreen;
analogWrite(RedledPin, VoltG);
}
I use for the receiver Arduino the code from Reply #23
Post your complete program so that we can see all the details. The devil is in the details - especially in programming.
I think the relevant code is in Reply #25 rather than #23
I didn't know that the Programming for serial communication is so difficult
It's not really difficult - you just need a systematic approach. Once you have a function that works you can just copy and paste into any program that needs it.
Here is the complete code, I mark my part with comment
I use the Serial Monitor to see my result.
as an an example: For the test I write the command in the Serial Monitor for 9 V:
<XRed = 9>
Now i want to integrate the values "9" in this function
VoltR = 25.5 * XRed // XRed = 9
// Code for Receiver Arduino
const byte numChars = 90;
char receivedChars[numChars];
boolean newData = false;
int RedledPin = 9; // Red LED, connected to digital pin 9
int GreenledPin = 10; // Red LED, connected to digital pin 10
float XRed;
float XGreen;
void setup() {
Serial.begin(9600);
Serial.println("<Arduino is ready -->");
}
void loop() {
recvWithStartEndMarkers();
showNewData();
doOtherStuff();
led(); // <------------- declaration the function LED
}
void recvWithStartEndMarkers() {
static boolean recvInProgress = false;
static byte ndx = 0;
char startMarker = '<';
char endMarker = '>';
char rc;
// if (Serial.available() > 0) {
while (Serial.available() > 0 && newData == false) { // <<== NEW - get all bytes from buffer
rc = Serial.read();
if (recvInProgress == true) {
if (rc != endMarker) {
receivedChars[ndx] = rc;
ndx++;
if (ndx >= numChars) {
ndx = numChars - 1;
}
}
else {
receivedChars[ndx] = '\0'; // terminate the string
recvInProgress = false;
ndx = 0;
newData = true;
}
}
else if (rc == startMarker) {
recvInProgress = true;
}
}
}
void showNewData() {
if (newData == true) {
Serial.print("This just in ... ");
Serial.println(receivedChars);
newData = false;
}
}
void doOtherStuff() {
delay(20); // <<===NEW - This just simulates time spent elsewhere in a big program
}
void led() // <--------
{
int VoltR = 25.5 * XRed; // the MAX is 10V : 10volt *25.5 = 255
analogWrite(RedledPin, VoltR);
Serial.print(" val for LED red: "); // <---- i can see the result when i opnen the Serial Monitor
Serial.println(VoltR);
int VoltG = 25.5 * XGreen; // the MAX is 10V : 10volt *25.5 = 255
analogWrite(GreenledPin, VoltG);
Serial.print(" val for LED green: ");
Serial.println(VoltG);
delay (1000);
}
Your comment
led(); // <------------- declaration the function LED
should be
led(); // <------------- call the function LED
You can remove the function doOtherStuff() and all references to it. It just wastes time - which is what it was designed for.
You might want to consider sending simpler commands.
For example <XRed = 9> could probably be reduced to and then the data could be parsed more easily with, for example
In serial input basics there is a parse example. As written it is designed for Comma Separated Values (CSV) but it would be easy to change it to use the = sign as the separator
You might want to consider sending simpler commands.
For example <XRed = 9> could probably be reduced to and then the data could be parsed more easily with, for example
ledColour = receivedChars[0]
ledValue = receivedChars[1]
(...)
I don't know if this will work. Actually, the value of each colour can vary from 0 to 10, and if this is done like this you miss the value 10.
luisilva:
I don't know if this will work. Actually, the value of each colour can vary from 0 to 10, and if this is done like this you miss the value 10.
Fair point. I had not realized that.
But it could still be simplified more than the OP's present system.
For instance he could use Hex values which allows 0 to 15 in a single character
Really the important point is that if the parts have a fixed length there would be no need to search for the relevant bytes.
Actually, the value of each colour can vary from 0 to 10, and if this is done like this you miss the value 10.
If you need to send a specific value to a specific component, you might try something similar to the below servo control code.
//zoomkat 11-22-12 simple delimited ',' string parse
//from serial port input (via serial monitor)
//and print result out serial port
//multi servos added
// Powering a servo from the arduino usually *DOES NOT WORK*.
String readString;
#include <Servo.h>
Servo myservoa, myservob, myservoc, myservod; // create servo object to control a servo
void setup() {
Serial.begin(9600);
//myservoa.writeMicroseconds(1500); //set initial servo position if desired
myservoa.attach(6); //the pin for the servoa control
myservob.attach(7); //the pin for the servob control
myservoc.attach(8); //the pin for the servoc control
myservod.attach(9); //the pin for the servod control
Serial.println("multi-servo-delimit-test-dual-input-11-22-12"); // so I can keep track of what is loaded
}
void loop() {
//expect single strings like 700a, or 1500c, or 2000d,
//or like 30c, or 90a, or 180d,
//or combined like 30c,180b,70a,120d,
if (Serial.available()) {
char c = Serial.read(); //gets one byte from serial buffer
if (c == ',') {
if (readString.length() >1) {
Serial.println(readString); //prints string to serial port out
int n = readString.toInt(); //convert readString into a number
// auto select appropriate value, copied from someone elses code.
if(n >= 500)
{
Serial.print("writing Microseconds: ");
Serial.println(n);
if(readString.indexOf('a') >0) myservoa.writeMicroseconds(n);
if(readString.indexOf('b') >0) myservob.writeMicroseconds(n);
if(readString.indexOf('c') >0) myservoc.writeMicroseconds(n);
if(readString.indexOf('d') >0) myservod.writeMicroseconds(n);
}
else
{
Serial.print("writing Angle: ");
Serial.println(n);
if(readString.indexOf('a') >0) myservoa.write(n);
if(readString.indexOf('b') >0) myservob.write(n);
if(readString.indexOf('c') >0) myservoc.write(n);
if(readString.indexOf('d') >0) myservod.write(n);
}
readString=""; //clears variable for new input
}
}
else {
readString += c; //makes the string readString
}
}
}
Hi zoomkat,
I have tried out your code, and it works. But I can see a little problem with servos.
While i rotate Poti1 to set up Servo1, the other few Servo shake a little bit (about one degree).
I think the Signal disturbs other servos. Is there a possibility that “digital outputs” separate from each other to avoid the interaction?
For example, if I use two potis and two servos on one Arduino board, the servo will work very fine without any interaction.
If you wants, I can upload a video on vimeo to show my problem.
For example, if I use two potis and two servos on one Arduino board, the servo will work very fine without any interaction.
The most common issues with servos is trying to power the servos from the arduino instead of from an external power supply, and failing to connect the servo ground to the arduino ground.