Offline
Newbie
Karma: 0
Posts: 24
|
 |
« on: July 25, 2012, 02:11:09 pm » |
Hello, I've been struggling with this for quite a while, so I'm hoping for a few clues. The following is just a simplified test I'm running. I've got 2 Arduinos communicating via hardware serial, and sharing pretty much the same code (see below). In principle the master sends 111 then waits for a response (112 from slave). Yet even though the enable pins (I'm using RS485) are set low on the slave, no value seems to be getting through. I've added a delay on the slave before it sends a response, so the master has time to bring the enable pin low; 300 ms, maybe too long? I've tested the Arduinos with two other sketches designed to just send a byte array from master to slave, and that works (the slave prints a confirmation response). It works when I reverse the roles too, so I'm guessing this has to do with the high/low timing on the enable pins. Any help would be vastly appreciated, I'm trying to complete an art installation by the end of August. Thank you so much! MASTER const int pinEnable = 2; byte hello = 111; byte inRead = 0; boolean received = true;
void setup () { pinMode(pinEnable,OUTPUT); Serial.begin(57600); }
void check () { digitalWrite(pinEnable, LOW); inRead = Serial.read(); if (inRead == 112) { received = true; } } void loop() { check(); if (received == true) { Serial.write(inRead); digitalWrite(pinEnable, HIGH); Serial.write(hello); digitalWrite(pinEnable, LOW); received = false; } }
---------------------------------- SLAVE const int pinEnable = 2; byte helloBack = 112; byte inRead = 0; boolean received = true;
void setup () { pinMode(pinEnable,OUTPUT); Serial.begin(57600); }
void check () { digitalWrite(pinEnable, LOW); inRead = Serial.read(); if (inRead == 111) { received = true; } } void loop() { check(); if (received == true) { delay(300); Serial.write(inRead); digitalWrite(pinEnable, HIGH); Serial.write(helloBack); digitalWrite(pinEnable, LOW); received = false; } }
|
|
|
|
« Last Edit: July 25, 2012, 04:14:02 pm by inoukdemers »
|
Logged
|
|
|
|
|
Massachusetts, USA
Offline
Tesla Member
Karma: 98
Posts: 6386
|
 |
« Reply #1 on: July 25, 2012, 02:17:57 pm » |
How are the two connected? What RS485 buffer are you using? Are the grounds connected?
|
|
|
|
|
Logged
|
|
|
|
|
Offline
Newbie
Karma: 0
Posts: 24
|
 |
« Reply #2 on: July 25, 2012, 02:25:42 pm » |
I'm using two MAX485s (CPA1121) between the Arduinos, each grounded to their respective Arduino (the setup is described here: http://www.gammon.com.au/forum/?id=11428 ) With prior sketches this was working fine. I suspect it's more of a code issue. Do you see anything wrong on that end?
|
|
|
|
« Last Edit: July 25, 2012, 03:48:28 pm by inoukdemers »
|
Logged
|
|
|
|
|
Offline
Newbie
Karma: 0
Posts: 24
|
 |
« Reply #3 on: July 25, 2012, 05:05:41 pm » |
Anyone?
|
|
|
|
|
Logged
|
|
|
|
|
Massachusetts, USA
Offline
Tesla Member
Karma: 98
Posts: 6386
|
 |
« Reply #4 on: July 25, 2012, 05:50:06 pm » |
You should take out the lines where you send inRead before you enable the transmitters. Serial.write(inRead); ///////// Get rid of this line digitalWrite(pinEnable, HIGH); Serial.write(hello); digitalWrite(pinEnable, LOW);
You can probably take the pinEnable line out of check() an put it in setup() since it only has to be done once.
|
|
|
|
|
Logged
|
|
|
|
|
Offline
Newbie
Karma: 0
Posts: 24
|
 |
« Reply #5 on: July 25, 2012, 05:59:55 pm » |
Hey John, Absolutely, I was being redundant largely out of paranoia. In the meantime, your initial hunch was right. I added a second pair of 620 Ohm resistors on the slave-end MAX485, and it did the trick! The Gammon diagram only showed one pair. Thanks for putting the bug in my ear! I also simplified the code. Here it is: MASTER const int pinEnable = 2; byte hello = 111;
void setup() { pinMode(pinEnable,OUTPUT); Serial.begin(57600); } void loop() { digitalWrite(pinEnable, LOW); byte inRead = Serial.read(); if (inRead = 112) { Serial.write(inRead); delay(500); digitalWrite(pinEnable, HIGH); delay(1); Serial.write(hello); digitalWrite(pinEnable, LOW); } }
SLAVE const int pinEnable = 2; byte helloBack = 112;
void setup() { pinMode(pinEnable,OUTPUT); Serial.begin(57600); digitalWrite(pinEnable, HIGH); Serial.write(helloBack); digitalWrite(pinEnable, LOW); } void loop() { byte inRead = Serial.read(); if (inRead = 111) { delay(500); // adjust this delay as needed digitalWrite(pinEnable, HIGH); delay(1); // give time for master to go LOW Serial.write(helloBack); digitalWrite(pinEnable, LOW); } }
|
|
|
|
« Last Edit: July 25, 2012, 06:01:42 pm by inoukdemers »
|
Logged
|
|
|
|
|
nr Bundaberg, Australia
Offline
Tesla Member
Karma: 73
Posts: 6839
Scattered showers my arse -- Noah, 2348BC.
|
 |
« Reply #6 on: July 25, 2012, 06:54:28 pm » |
each grounded to their respective Arduino But there also needs to be a GND connection between the two. You are probably getting away with it now because the two Arduinos are running of the same PC or something and therefore getting a similar/same GND but if your intention is to have them more independent you need the third wire. Technically Nick's schematic is correct but for newbies I think it should show the third wire to make it obvious. If your Arduinos are close together and/or the bit rates are slow I don't see why you needed the extra resistors, in fact they are failsafe resistors not terminating resistors . But I won't argue with success  EDIT: In the slave setup() function you have this digitalWrite(pinEnable, HIGH); Serial.write(helloBack); digitalWrite(pinEnable, LOW);
As there's no delay I doubt that byte ever sees the light of day. ANOTHER EDIT: digitalWrite(pinEnable, HIGH); delay(1); Serial.write(hello); digitalWrite(pinEnable, LOW); Same problem, the delay should be after the write(). Are you sure this code is working  Have you verified that the master actually sees the return byte? _____ Rob
|
|
|
|
« Last Edit: July 25, 2012, 07:16:48 pm by Graynomad »
|
Logged
|
|
|
|
|
Offline
Newbie
Karma: 0
Posts: 24
|
 |
« Reply #7 on: July 25, 2012, 07:08:11 pm » |
Graynomad, I'm glad you mentioned that.
Just to make sure I understand what you mean by "third wire":
I have a 2-wire + ground (threaded wire) cable at home I planned on using. I guess I would connect two of the wires to A & B on the MAX485, but then would the receive enable pin connect to GND on the Arduino, whereas the actual GND pin on MAX485 would connect back to the master via the cable?
Also, whereas with the above sketches I could easily send bytes back to the master, when I change the sketch to use analogRead() (read as an int, then converted to byte), it doesn't read correctly on the master end - it always reads 255:
SLAVE:
int sensor = analogRead(A0)/4; Serial.write((byte)sensor);
MASTER:
byte inRead = Serial.read(); if (inRead > 0) { Serial.print(inRead, DEC); }
|
|
|
|
« Last Edit: July 25, 2012, 07:10:42 pm by inoukdemers »
|
Logged
|
|
|
|
|
nr Bundaberg, Australia
Offline
Tesla Member
Karma: 73
Posts: 6839
Scattered showers my arse -- Noah, 2348BC.
|
 |
« Reply #8 on: July 25, 2012, 08:24:20 pm » |
Short answer, ALL grounds should be connected together, that cable should be good, use the "third wire" to connect the grounds at both ends. The MAX485 RE pins at both ends should be pulled low (grounded) as well. byte inRead = Serial.read(); if (inRead > 0) { Serial.print(inRead, DEC); } This is wrong, you should wait for a character to be available then read it. As it is the Serial.read() is returning -1 (no characters to read) which happens to be 0xFF or 255. Try byte inRead; if (Serial.available() > 0) { inRead = Serial.read(); Serial.print(inRead, DEC); } ______ Rob
|
|
|
|
« Last Edit: July 25, 2012, 08:26:24 pm by Graynomad »
|
Logged
|
|
|
|
|
Anaheim CA.
Offline
Edison Member
Karma: 31
Posts: 2311
Experienced old Whitebeard with a Full head of Hair...
|
 |
« Reply #9 on: July 25, 2012, 09:56:04 pm » |
The device to device grounds must be in place for a reference for the '485 serial differential data transfer, what if there were a 10 to 20 volt differential in the local grounds (Very Possible) now the question is without that ground... Referenced to what? and since the Max485 shares the same power supply as the Arduino again the ground from the '485 device is necessary so the Arduino can read/write to the device. It must also be explained that the ground is usually not explained but rather explicit. We all that use RS485 regularly Assume the ground rather that explain what is to us obvious. I hope this helps.
Doc
|
|
|
|
|
Logged
|
“The solution of every problem is another problem.” -Johann Wolfgang von Goethe
|
|
|
|
Offline
Newbie
Karma: 0
Posts: 24
|
 |
« Reply #10 on: July 25, 2012, 10:14:45 pm » |
Graynomad,
I just read your edit, and indeed, I'm realizing the value I'm apparently getting back on the Master is a phantom. If I try incrementing the sent value from the slave, I see on the master that it doesn't change; d'oh!
I'll set the delay so it's after the write function and see what happens.
Docedison, I don't know who this 'we that use RS485' is, but to a non-engineer artist, let me tell you, the ground issue is not obvious at all! I'm a big fan of explicit ;-) But your point is well taken.
|
|
|
|
« Last Edit: July 25, 2012, 10:45:52 pm by inoukdemers »
|
Logged
|
|
|
|
|
Offline
Newbie
Karma: 0
Posts: 24
|
 |
« Reply #11 on: July 25, 2012, 10:40:44 pm » |
OK, the code below works, since the incremented values on the slave are being received by the master. I have to reset the slave to get the thing going, and oddly enough when I open Serial Monitor on the master the thing stops(!) But at least I know the data is coming in correctly. I also made sure the RE and GND pins from the slave MAX485 were connected to the master Arduino's GND. That tip on placing the delay after the write function was awesome! Thanks again guys. Here's the code: const int pinEnable = 2; byte hello = 111; byte inRead;
void setup() { pinMode(pinEnable,OUTPUT); Serial.begin(57600); } void loop() { digitalWrite(pinEnable, LOW); if (Serial.available() > 0) { inRead = Serial.read(); if (inRead >= 112) { Serial.println(inRead, DEC); delay(500); digitalWrite(pinEnable, HIGH); Serial.write(hello); delay(10); // delay should be AFTER the write digitalWrite(pinEnable, LOW); } } }
SLAVE const int pinEnable = 2; byte helloBack = 112; byte inRead;
void setup() { pinMode(pinEnable,OUTPUT); Serial.begin(57600); digitalWrite(pinEnable, HIGH); Serial.write(112); delay(10); digitalWrite(pinEnable, LOW); } void loop() { if (Serial.available() > 0) { inRead = Serial.read(); if (inRead == 111) { helloBack += 1; Serial.println(inRead, DEC); delay(500); // adjust as needed digitalWrite(pinEnable, HIGH); Serial.write(helloBack); delay(10); // give time for master to go LOW digitalWrite(pinEnable, LOW); } } }
|
|
|
|
|
Logged
|
|
|
|
|
Massachusetts, USA
Offline
Tesla Member
Karma: 98
Posts: 6386
|
 |
« Reply #12 on: July 26, 2012, 08:01:36 am » |
oddly enough when I open Serial Monitor on the master the thing stops(!)
Starting Serial Monitor, like starting an Upload, resets the Arduino.
|
|
|
|
|
Logged
|
|
|
|
|
Offline
Newbie
Karma: 0
Posts: 24
|
 |
« Reply #13 on: July 26, 2012, 12:03:58 pm » |
Good to know, thanks John.
|
|
|
|
|
Logged
|
|
|
|
|
|