My program is for the Mega and it uses 2 serial ports as receivers and then it is supposed to repeat anything received to the Monitor after every 60 chars.
I expect to get Hexidecimal numbers but, I have mostly got random characters. I want the program to repeat anything received no matter if it text or a number of any kind.
Please have a look, any suggestions appreciated:
/*
Mega multple serial test
Receives from the main serial port, sends to the others.
Receives from serial port 1, sends to the main serial (Serial 0).
This example works only on the Arduino Mega
The circuit:
* Any serial device attached to Serial port 1
* Serial monitor open on Serial port 0:
created 30 Dec. 2008
by Tom Igoe
This example code is in the public domain.
*/
String readString1;
char c1;
String readString2;
char c2;
void setup() {
// initialize both serial ports:
Serial.begin(115200);
Serial1.begin(50000);
Serial2.begin(10400);
Serial.print(" IM HERE 2 ");
}
void loop() {
// read from port 1, send to port 0:
if (Serial1.available() >0) {
char c1 = Serial1.read();
readString1 += c1;
}
if (Serial2.available() >0) {
char c2 = Serial2.read();
readString2 += c2;
}
if (readString1.length() >60) {
Serial.print("50,000");
Serial.print( "baud ");
Serial.println(readString1);
readString1="";
}
if (readString2.length() >60) {
Serial.print(" 10,400Baud ");
Serial.println(readString2);
readString2="";
}
}
Well its doing exactly what you coded it to do. A "char" is a data type that will represent a signed 8 bit number. It can be binary data, character data, whatever. Its just numbers. Hex is just a different way to represent a value in a char (or in any data type). If you try to print a string of chars, its going to print them according to their values int eh ASCII table.
Foe example, the space character is represented by a value of decimal 32, or hex 0x20. Have a look here:
I am not too familiar with the String class, but you might have a look at its docs and see if there is a member function that can print one character at a time. You can probably do something like this:
I have read about the things you have said in the reference area so, what you said does make sense. I think I will run your example when I get home and change the input strings to hex numbers and check the results to learn process.
I am starting to think that I have a noise problems on my serial connection. I am connecting to a motorcycle through a diagnostic connector and I may need to do some filtering. I get some numbers that look possibly correct but, I mostly get "square O" symbols.
I just wanted to make sure my code is the correct approach to capture any and all output.
You're welcome. It could be noise, but consider that if you're getting a character like that then the stream of data you are getting is probably binary data, as opposed to character data. Character data limits the range of possible values of any single byte to 0 to 127. This is simple to read and parse.
Binary data is a whole different story. If its binary data, each byte will be from 0 to 255 so you should use an unsigned char, not a char. Also, you need to find out how the data is structured. You will probably need to combine adjacent bytes to get any particular value.
Do you have the docs for the data format so you can know what it is for sure?
That might be it! I might need unsigned char. I will try that when I get home.
I am running my circuit through a level converter and an inverter to get the serial correct for Arduino serial.
Although it is automotive communication, I do not believe the Sparkfun obd2 shield would work for this.
Here is most of the information I can offer you about the communication. I am using ISO 14230 KWP2000 set to 50,000 baud "long story on why I know to run that speed" Normally it would be 10.4k baud but it has been modified to run faster:
ISO 9141-2. This protocol has an asynchronous serial data rate of 10.4 kBaud. It is somewhat similar to RS-232, however the signal levels are different, and communications happens on a single, bidirectional line without additional handshake signals. ISO 9141-2 is primarily used in Chrysler, European, and Asian vehicles.
pin 7: K-line
pin 15: L-line (optional)
UART signaling
K-line idles high, with a 510 ohm resistor to Vbatt
The active/dominant state is driven low with an open-collector driver.
Message length is restricted to 12 bytes, including CRC
ISO 14230 KWP2000 (Keyword Protocol 2000)
pin 7: K-line
pin 15: L-line (optional)
Physical layer identical to ISO 9141-2
Data rate 1.2 to 10.4 kBaud
Message may contain up to 255 bytes in the data field
With a call set of numbers 80 F1 12 34 I am supposed to get specific order of response data.
If I do everything correctly the data is supposed to look basically like this:
In an effort to fully understand "unsigned char" I found this on a google search:
I think I do need unsigned char.
All 8-bit data types hold exactly 256 different values: 00 to FF hex or 00000000 to 11111111 binary. The difference between signed and unsigned is how those bits are interpreted by the compiler.
Unsigned characters use the linear range of 00000000 to 11111111 as 0 to 255. There is no possibility of a negative value. Note that although the name 'char' does not imply that the data type is a number, it is - just as any data stored in a computer is a number. a char is just an 8-bit integer - signed or unsigned.
Signed characters rearrange the order of the linear binary values from 00000000 to 11111111 to take advantage of what is known as the two's complement system. It simply considers the integer part to be 7-bits long and the most significant bit to be the sign bit. Note in the following that positive numbers (1-127) have 0 as the most significant bit and the negative numbers (-128 to -1) have 1 as the most significant bit.
I changed the char to unsigned char and I am still having trouble. I am still getting the squared 0's and Y's but, I can see a repeating pattern. I will continue trying to work this out though.
An unsigned char can hold a value from 0 to 255. A signed char is -127 to 128. In a signed type (signed int, signed char, etc) the left most bit is used as a sign bit to decide if the value represented by the other 7 bits is negative or positive.
Looking at what you say the data should be, you want to use unsigned char.
I have been away from this sketch for a while but, I was reading a post that got me thinking about this repeater program that I have had trouble with.
Skyjumper had instructed me use this line to display to my serial monitor. Serial.println(myString[0], HEX);
However, while I did make other changes that he recommended for my code, I accidentally left off the ,HEX part of the print code. My results were strange characters. I now realize that I might have been getting characters from the Ascii table.
Tonight I have made a change to the code that I think will work but, I will have to wait until Saturday to give it a try.
....One other change to the code is my usage of a String index "int i". This is unfamiliar territory so, I am hoping I am using it correctly.
String readString1;
unsigned char c1;
int i = 0;
void setup() {
// initialize both serial ports:
Serial.begin(115200);
Serial1.begin(50000);
Serial.print(" IM HERE ");
}
void loop() {
// read from port 1, send to port 0:
if (Serial1.available() >0) {
c1 = Serial1.read();
for (int i = 0; i < 60; i++){
readString1[i] = c1;
}
}
if (readString1.length() >60) {
i = 0;
Serial.print("50,000");
Serial.print( "baud ");
for (int i = 0; i < 60; i++){
Serial.println(readString1[i], HEX);
}
i = 0;
readString1="";
}
}
A String object is allocated just big enough to hold the initial value. How big do you supposed this String is?
String readString1;
That's right. Not very.
if (Serial1.available() >0) {
c1 = Serial1.read();
for (int i = 0; i < 60; i++){
readString1[i] = c1;
}
If there is at least one character available to read. read all 60 of them. Hmmm. I don't think so.
This implies, anyway, that you know how big readString needs to be. Which implies that using String is completely unnecessary. A char array would work even better, and you can properly size it.
Serial.print("50,000");
Serial.print( "baud ");
for (int i = 0; i < 60; i++){
Serial.println(readString1[i], HEX);
}
Jam 50,000 and baud right up against each other, and then print each character on it's own line. Well, OK, I guess.
Thank you PaulS for your reply. You are definitely helping me learn, and at the same time I was a laughing at your statements about my code. I hate making silly mistakes but, I had to laugh about how funny the results of my code would be.
First I have made corrections to each portion you have mentioned. I am going to post that code. Then, I am going to modify it and change the string to an array and post that for examination.
String readString1[61] // 60 + 1 for null termination;
while (Serial1.available() >0 && i < 60) {
c1 = Serial1.read();
for (int i = 0; i < 60; i++){
readString1[i] = c1;
Serial.print("50,000");
Serial.print( "baud ");
for (int i = 0; i < 60; i++){
Serial.print(readString1[i], HEX);
}
String readString1[61]; // 60 + 1 for null termination
unsigned char c1;
int i = 0;
void setup() {
// initialize both serial ports:
Serial.begin(115200);
Serial1.begin(50000);
Serial.print(" IM HERE ");
}
void loop() {
// read from port 1, send to port 0:
while (Serial1.available() >0 && i < 60) {
c1 = Serial1.read();
for (int i = 0; i < 60; i++){
readString1[i] = c1;
}
}
if (readString1.length() >= 60) {
i = 0;
Serial.print("50,000 ");
Serial.print( "baud ");
for (int i = 0; i < 60; i++){
Serial.print(readString1[i], HEX);
}
i = 0;
readString1="";
}
}
String readString1[61] // 60 + 1 for null termination;
First, the semicolon belongs at the end of the statement, not the end of the comment.
Second, now you have an array of String objects, not an array of characters.
Forget you ever heard of the String class.
while (Serial1.available() >0 && i < 60) {
c1 = Serial1.read();
for (int i = 0; i < 60; i++){
readString1[i] = c1;
So, there are three characters to read, and i is 8. Read a character, and make 60 copies of it. Hmmm. The point being?
What is sending data to the serial port? How do you know how many characters to read? In other words, what defines a packet (a word or sentence, if you will)?
What is sending data to the serial port? How do you know how many characters to read? In other words, what defines a packet (a word or sentence, if you will)?
If I understood VB programming this task might be easier but, here is my explaination.
Currently, my laptop is running a open source VB.net program through a FTDI cable and a level converter to talk to my motorcycle ECU. I am trying to record the serial data to my monitor so that I can be sure of the data format, length, and then resulting integers after calculations are done. I have some general information about what is being transmitted but, I am not positive about the message length. So for now I thought I would run my program and look for the pattern and then adjust my character capture size.
This is one possible example of both transmit to the ECU and receive back. It should be noted that the transmit TX will be "echoed" on the receive RX.
Here is the latest version of my repeater code. I am not sure if I should zero out the array contents after use or if it would even matter.
I got rid of the String and hopefully changed it correctly to an array. Also, I changed the part where the for loop made copies of the same read over and over. Lastly, I made sure it compiles so I don't have any silly ; mistakes.
unsigned char readarray1[60]; // index starting at 0 for 60 characters + 1 for null termination
unsigned char c1;
int i = 0;
void setup() {
// initialize both serial ports:
Serial.begin(115200);
Serial1.begin(50000);
Serial.print(" IM HERE ");
}
void loop() {
// read from port 1, send to port 0:
while (Serial1.available() >0 && i < 59) {
c1 = Serial1.read();
if (i < 59) {
i++;
readarray1[i] = c1;
}
}
if (i >= 59) {
i = 0;
Serial.print("50,000 ");
Serial.print( "baud ");
for (int i = 0; i < 59; i++){
Serial.print(readarray1[i], HEX);
readarray1[i]= 0; ///<<<<<<<<<<<<<<< should I clear the array like I did with the string?
}
i = 0;
}
}
Is this a guess, or do you know this for certain? If so, then you know how much data you need to read.
So, you could wait until there are 4 bytes of data. The 4th byte then defines how much more data to wait for.
while (Serial1.available() >0 && i < 59) {
c1 = Serial1.read();
if (i < 59) {
i++;
readarray1[i] = c1;
}
This is better. The if test is not required, though, since the while loop will not execute is i is greater than or equal 59.
However, there is still a problem. If there are 8 bytes in the buffer, out of a 45 byte packet, that is all you will read. Then, you treat it like a complete packet. That is the bad part.
readarray1[i]= 0; ///<<<<<<<<<<<<<<< should I clear the array like I did with the string?
That isn't really necessary. You simply need to reset the index to 0.