Help with Serial Output

I am trying to integrate a C++, sh, and arduino program into one. Right now, I have a simple program:
Arduino Sketch

int incomingByte = 0;      // for incoming serial data

void setup() {
      Serial.begin(9600);      // opens serial port, sets data rate to 9600 bps
}

void loop() {

      // send data only when you receive data:
      if (Serial.available() == 1) {
            // read the incoming byte:
            incomingByte = Serial.read();
                Serial.flush();

            // say what you got:
            //Serial.print("I received: ");
            incomingByte=incomingByte - '0';
                Serial.print(incomingByte); //Problem is here
                digitalWrite(13, incomingByte);
                Serial.flush();
        
      }
}

SH Code

#!/bin/sh
while : 
do
read -n 1 -s key
cat > /dev/tty.usbserial-A800eFDb <<EOT
$key
EOT
done

The sh sends keypresses to the arduino, which outputs them on the built led. (1 is on, 0 is off). The line that says “problem is here” is not working. If i use Serial.println() it works, but not if I use serial.print(). I want it to output a continuos stream of ones and zeros (which would echo the led state.)
Here is what I get for output with the above programs.
1-380-381-380-380-381-38
I had entered the following:
101001
and for some reason it adds “-38” after it.

I am still learning myself but if you want only 0 and 1 output perhaps change the variable to be a binary value by putting ,bin after it. IE: Serial.print(incomingByte,BIN); its listed in the reference under serial.print. I hope that helps a little.

But that's not the problem. If I type in a '1' in terminal, the arduino outputs

1-38

so what's the -38 part? If I add ,bin, then i'll get

1 *bnary code for -38*

which I don't want. I tried to flush the serial bufer after it read a one or a zero, but that didn't work. I need this to work for a project that I'm doing. I need a .h file (which has a few thousand 1s and 0s) to be sent to the arduino, one bit at a time. This can be done w/ shell script and C++, but the problem is having the arduino get the it correctly. 1 must ouput 1, 0 must output 0. Then, from there, I am going to send the whole string of 1s and 0s through TVout library, onto my TV.

Is this something with my terminal? If I use the built-in serial monitor, it works. Just not terminal. But then, why does println() work??!?!?!?!

This is a guess, but -38 == 10 - '0' , in other words the -38 could come from the computer sending ASCII code 10 to the Arduino. And ASCII code 10 is a newline. So my guess would be that your shell script is sending a newline after transmitting the keypress, and your program is interpreting that as -38.

I think you want to use atoi

This is untested, but try something like this: EDIT: Ok, I tried to test this. It doesnt work, but atoi is the route I think you want. Try searching around the forum.

int incomingByte = 0;      // for incoming serial data
int data = 0;

void setup() {
      Serial.begin(9600);      // opens serial port, sets data rate to 9600 bps
}

void loop() {

      // send data only when you receive data:
      if (Serial.available() == 1) {
            // read the incoming byte:
            incomingByte = Serial.read();
                Serial.flush();

            // say what you got:
            //Serial.print("I received: ");
            data = atoi(incomingByte);
                Serial.print(data); //Problem is here
                digitalWrite(13, data);
                Serial.flush();
        
      }
}
      if (Serial.available() == 1) {

What happens if 2 bytes arrive on the serial port before the Arduino gets back to check it again?

               Serial.flush();

You only call this function if there was one byte in the buffer, and you removed that byte. What possible reason is there for emptying a buffer that you know is empty?

Almost every time I see this is code, it is a clue that the coder has no clue what they are doing. Improve my perception of your skills by removing this call, unless you have some specific, non-obvious reason for calling this function. If you have such a reason, why are there no comments to explain why it is needed?

            data = atoi(incomingByte);

Did you read anything about the atoi function? Do you know that atoi expects a NULL terminated array of characters, not an int?

How can you expect reasonable results from a function if you don't pass it good input?

Sorry about all that… I was just trying to fix the problem. If I send over a 1 from terminal into the arduino, then my arduino gets four characters:
the 1 or 0 I typed

3
8

So I’m trying to get

Input: 1
Output: 1

Not

Input: 0
Output: 0-38

The first thing that you need to by is determine the values of the bytes being sent/received, not the ASCII representation of those bytes.

In a simple sketch, read a byte, and print it using:

Serial.print("Byte read: ");
Serial.print(incomingByte, DEC);
Serial.println();

Once you know what you are getting, it will be much easier to know what to ignore.

But that's not the problem. I need to know how to get rid of the -38 part! Here's my arduino code:

char text;
int num;

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

void loop () {
  while (Serial.available() == 0) {}
  text = Serial.read();
  num = int(text) - '0';
  Serial.print(num);
  
}

Which works fine w/ Serial Monitor. But if I use terminal to input, say,

0110

I will get

0-381-381-380-38

on the serial monitor. Help!

I will try once more. Create a sketch that does nothing but read a byte from the serial port, and echo the decimal value of that byte. Do not subtract ‘0’ from it, or do any other processing.

What you will likely find is that the shell script is adding carriage return/line feed data after each key sent.

But, without being able to see EXACTLY what is received, it is difficult to know how to help you.

[edit]n - ‘0’ = -38, when n = 10, which is the ascii code for line feed, so you simple need to test that text >= ‘0’ && text <= ‘9’ before subtracting ‘0’ from it[/edit]

So

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

void loop () {
     if (Serial.available() > 0) {
            int val = Serial.read();
            Serial.print(val);
     }
}

So

No. Read the code I suggested that you use.

OK. I got that. But one question. Why would sh be sending a line feed if I'm not pressing return? My sh code reads the characters as they are inputed and does not wait for a terminating character or return. But something like:

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

void loop () {
     if (Serial.available() > 0) {
            int val = Serial.read();
            if (val == '0' || val == '1') {Serial.print(val);} //I only want ons or offs
     }
}

Why would sh be sending a line feed if I'm not pressing return?

Your script is reading a key press, and using cat to send the data to the serial port.

Perhaps cat is adding the line feed.

Here it is

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

void loop () {
     if (Serial.available() > 0) {
            int val = Serial.read();
            if (val == '0' || val == '1') {Serial.print(val-'0');} //I only want ons or offs
     }
}

And it works!

Thanks to you all!