In your code, you test to see if any characters are available from Serial3 but then you blindly read in 15 characters. How do you know 15 characters are available? the Serial3.available() function actually returns the number of chars available.
Since Serial communication is VERY slow compared to how fast the Arduino is running, a better approach would be to read the input into a global buffer and increment a global counter. When the counter hits 15, then do something...
Check the great posting by Robin2 about Serial basics and different ways to do it reliably.
Interesting that it is trying to read from an input buffer. The baud rates match up between arduino and scale, and Ive been trying switching the TX and RX cables and retrying the same tests. Either I get a string of 255, or no communication at all and only "can not communicate with load cell"
@blh64 good to know that it returns the number of characters. The 15 count came from how many characters I thought were in each output string from the scale. I'll find the post by robin2, I remember coming across it looking for information on Serial.
GodOfHammers:
Interesting that it is trying to read from an input buffer.
That's just how Serial communication works - every Serial interface has a built in input buffer and a built in output buffer.
Sometimes the buffers are implemented in hardware (e.g. UART/USART) or in software (softwareSerial.h ring buffer). Also, matching bauds are required to make sense of the data, but this does not guarantee that you will always read each byte as soon as you receive it - hence the need for a buffer.
If Serial interfaces shared a clock signal and were "synchronous" (e.g. I2C, SPI, etc) you wouldn't need a buffer.
Try using
if(Serial3.available() >= 15)
{
// do cool stuff with your 15 bytes of serial data
}
After reading Robin2's post about Serial communication, I understand how I would be able to implement an if statement to begin reading the information at the Start Transmission (STX, 02 on Ascii) character. I have yet to get a proper response from the scale though.
The simple example I wrote in #5 should work if I understand@sterretje and @Power_Broker correctly.
The Scale manual says that it is 8 data bits, 1 stop bits, no parity, no handshaking, do I have to incorporate this into my code anywhere?
sterretje:
Serial.read returns an int. Possible values 0..255 or -1.
Since max value it returns is 255, for all intents and purposes, it returns a byte - the extra 8 bits are worthless anway.
sterretje:
Because OP uses Serial.available() in the code in reply #5, Serial.read will never return -1 so it's safe to a variable of type byte.
Even if OP was trying to read from an empty buffer, OP could still use byte = read(). If he reads from the empty buffer, it'll still return -1.
Even if OP is trying to receive the unsigned 8-bit value 255, OP would still be able to receive that value perfectly fine with a variable of type byte. Idk, it's user preference and there is really nothing inherently wrong with doing byte = serial.read().
GodOfHammers:
The Scale manual says that it is 8 data bits, 1 stop bits, no parity, no handshaking, do I have to incorporate this into my code anywhere?
Serial#.begin(baud) automatically sets the port to 8 data bits, no parity, and 1 stop bit (SERIAL_8N1) and handshaking is unconfigurable anyway (don't worry about it).
It might be time to break out an o-scope...but first, post your latest code in tags.
Should I be using the oscilloscope to verify that anything is actually coming out of the TX and RX pins of the 9 pin connection?
This is the code I was trying for a bit, but because I was getting a string of 255 (even though thats -1/blank) I have been trying the previous code too.
I found why I was recording in sets of 15, "... the manual says that the serial data is made of 15 words (bytes), with constant 1st, 2nd last and last bytes"
These constant bytes are
STX, 02 in ASCII, Start Transmission
CR, 13 in ASCII, Carriage Return
LF, 10 in ASCII, Line Feed
Power_Broker:
Since max value it returns is 255, for all intents and purposes, it returns a byte - the extra 8 bits are worthless anway.
Even if OP was trying to read from an empty buffer, OP could still use byte = read(). If he reads from the empty buffer, it'll still return -1.
Even if OP is trying to receive the unsigned 8-bit value 255, OP would still be able to receive that value perfectly fine with a variable of type byte. Idk, it's user preference and there is really nothing inherently wrong with doing byte = serial.read().
If you read from an empty buffer into a variable of type byte, you can not receive -1 as a value. Instead, you will get the value 255 and can not distinguish that value from a valid 255 char, if you application may receive one.
I'm not exactly sure of the command format your scale expects, the manual only gives the single-letter commands but doesn't specify any line terminating characters, so you may have to experiment with that a bit. This sketch should request the data from the scale every 10 seconds and print it out when received, see if it will work. I'm guessing at the weight request format, based on a Cardinal brand scale I have worked with. The function to receive the serial data is slightly modified from the example given in the Serial Input Basics page.
const int BAUD_IDE = 9600;
const int BAUD_LOAD_CELL = 9600;
const byte numChars = 15;
char receivedChars[numChars];
boolean newData = false;
unsigned long currentMillis;
unsigned long timerStart;
unsigned int timerDuration = 10000u;
void setup() {
Serial.begin(BAUD_IDE);
Serial3.begin(BAUD_LOAD_CELL);
Serial.println("<Arduino is ready>");
timerStart = millis();
//delay(250);
}
void loop() {
currentMillis = millis();
if ((currentMillis - timerStart) > timerDuration) {
timerStart = currentMillis;
requestLoadCellData();
}
recvWithStartEndMarkers();
if (newData == true) {
Serial.print("Data received from scale ... ");
Serial.println(receivedChars);
newData = false;
}
}
void requestLoadCellData() {
Serial3.print("\nR\r"); // ***** request to scale, you may need to remove the newline \n or carriage return \r
}
void recvWithStartEndMarkers() {
static boolean recvInProgress = false;
static byte ndx = 0;
char startMarker = 0x02; //ASCII STX
char endMarker = 0x0A; //ASCII LF
char rc;
while (Serial3.available() > 0 && newData == false) {
rc = Serial3.read();
if (recvInProgress == true) {
receivedChars[ndx] = rc;
ndx++;
if (ndx >= numChars) {
ndx = numChars - 1;
}
if (rc == endMarker) {
receivedChars[ndx] = '\0'; // terminate the string
recvInProgress = false;
ndx = 0;
newData = true;
}
}
else if (rc == startMarker) {
recvInProgress = true;
}
}
}
Looking at the manual, you have to have parameter C18 set to mode 3. You also have to have parameter C19 set to 9600 baud. Are both of these set correctly on the scale?
After that, you have to have the Tx->Rx and Rx->Tx and Gnd->Gnd wired correctly - did you check that?
Thanks so much for that response, When I read through the Serial Input Basics post that example was the one I planned to modify to use the STX and LF as the start and end markers. I set the scale to C18 = 3 mode and tried the code you posted with only "\n" removed, then with only "\r" removed and then with both removed and in the Serial monitor for all three cases all that was posted was "".
I have been changing the C18 parameter while running the same code, going through the different options to see if one causes a readout. Primarily trying C18 = 1 and C18 = 3. C19 is set to 9600 baud. Also Rx->Tx, Tx->Rx and Gnd -> Gnd are wired correctly.
that will let us see what, if anything, is being received.
Also, just to verify, you do have power connected to the RS232 converter, and you have verified that the RX and TX from the scale to the converter are connected properly.