Go Down

Topic: Reading from Serial (Read 4 times) previous topic - next topic

jair2k4

Nov 27, 2011, 08:08 pm Last Edit: Nov 27, 2011, 08:11 pm by jair2k4 Reason: 1
Ok guys, here's the setup

Computer -> wifi - > wrt54gs linksys router -> sparkfun logic level converter to 5v -> Arduino software serial on pins 8 and 9 on a Seeeduino board -> DFrobot dual H bridge driver shield -> tyco rebound RC chassis (same drive style as a tank chassis).

I can send data over serial from the arduino and using cat < /dev/tts/1 my router can see it in SSH. I cannot get data to send the other way to the arduino. In order to get commands to the h bridge and from there to the motors, i need to send data through the router over serial to the arduino.

This is based off of Jon Bennett's project (http://www.jbprojects.net/projects/wifirobot/)

Here is my code. I have tried 2 different routers with the exact same result. I am sure at this point it is a matter of coding to get my arduino to see the serial data. Jon had mentioned something about calling SWread to me, but i dont know enough about linux or processing to do this right. Can you guys give me a hand here? Again, If i set up a sketch to println something like "hello", i can see it just fine over ssh or telnet on the router. It's the communication going the other way that is necessary, and of course the one thing that isnt working for me.

Code:

Code: [Select]
// include the SoftwareSerial library so you can use its functions:
#include <SoftwareSerial.h>
#include <ctype.h>

#define bit9600Delay 84
#define halfBit9600Delay 42
#define bit4800Delay 188
#define halfBit4800Delay 94

int serialChar; // stores character of serial Input as integer
int serialLoop; // counter for serial read loop



unsigned long decay; // counter from last command
unsigned long decaylimit=100000; // 100,000 is about 5 seconds

#define rxPin 8
#define txPin 9
#define ledPin 13

// set up a new serial port
SoftwareSerial mySerial =  SoftwareSerial(rxPin, txPin);
byte pinState = 0;

void setup() {
   // define pin modes for tx, rx, led pins:
 pinMode(rxPin, INPUT);
 pinMode(txPin, OUTPUT);
 pinMode(ledPin, OUTPUT);
 // set the data rate for the SoftwareSerial port
 mySerial.begin(9600);
 mySerial.println("Hello"); // For debugging purposes
 

 //left/right motors
 pinMode(4, OUTPUT);
 pinMode(5, OUTPUT);
 pinMode(6, OUTPUT);
 pinMode(7, OUTPUT);
 //end debugging
}

int SWread()
{
 byte val = 0;
 while (digitalRead(rxPin));
 //wait for start bit
 if (digitalRead(rxPin) == LOW) {
   delayMicroseconds(halfBit9600Delay);
   for (int offset = 0; offset < 8; offset++) {
    delayMicroseconds(bit9600Delay);
    val |= digitalRead(rxPin) << offset;
   }
   //wait for stop bit + extra
   delayMicroseconds(bit9600Delay);
   delayMicroseconds(bit9600Delay);
   return val;
 }
}
void loop() {
 //check for serial communications
 if (SWread() > -1) {

   // decay counts the age of the last command
   // at the limit (100,000 = ~5 seconds, all signals are shut off
   if (decay > decaylimit) {
     digitalWrite(4, LOW); digitalWrite(5, LOW); digitalWrite(6, LOW); digitalWrite(7, LOW);
     // stop counting at limit, shut off all pins
   }
   else {
     decay++;
   }

   // this loop read whole strings. as soon as a string is detected
   // each character is evaluated. We only care about the first one.
   for (serialLoop=0; serialLoop < 16 && Serial.available(); serialLoop++) {
     serialChar = Serial.read();

     // echo for debugging only:
     mySerial.print(serialChar);

     // only do evaluation on the first letter (first loop)
     if (serialLoop==0) {

       // serialChar contains the ASCII code of the *first* character sent over serial when defined as int
       switch (serialChar) {

        // logical signals w s a d style any change shuts off previous command        
        case 119: //w - forward, pin 6+8
           digitalWrite(4, LOW); digitalWrite(5, LOW); digitalWrite(6, LOW); digitalWrite(7, LOW);
           digitalWrite(4, HIGH);
           digitalWrite(6, HIGH);            
           decay=0;            
           break;
        case 115: //s - backwards, pin 7+9
           digitalWrite(4, LOW); digitalWrite(5, LOW); digitalWrite(6, LOW); digitalWrite(7, LOW);
           digitalWrite(5, HIGH);
           digitalWrite(7, HIGH);            
           decay=0;            
           break;
        case 97: //a - left, pin 6+9
           digitalWrite(4, LOW); digitalWrite(5, LOW); digitalWrite(6, LOW); digitalWrite(7, LOW);
           digitalWrite(4, HIGH);
           digitalWrite(7, HIGH);            
           decay=0;            
           break;
        case 100: //d - right, pin 7+9
           digitalWrite(4, LOW); digitalWrite(5, LOW); digitalWrite(6, LOW); digitalWrite(7, LOW);
           digitalWrite(5, HIGH);
           digitalWrite(6, HIGH);            
           decay=0;            
           break;            
        case 113: //q - stop, pin 6+7+8+9 off
           digitalWrite(4, LOW); digitalWrite(5, LOW); digitalWrite(6, LOW); digitalWrite(7, LOW);
           decay = decaylimit;            
           break;            
       }
     }
   }
 }
}

PaulS

A couple of comments.
Code: [Select]
SoftwareSerial mySerial =  SoftwareSerial(rxPin, txPin);
SoftwareSerial is obsolete. NewSoftSerial is a much better replacement.

Code: [Select]
  pinMode(rxPin, INPUT);
  pinMode(txPin, OUTPUT);

You told the SoftwareSerial instance that these were its pins. What are you messing with them?


jair2k4

The code i am using is a kludge together of a bunch of different codes that i have been playing with. I have upgraded to new software serial. Please take a look and tell me what the issue could be. I can still send data from the arduino to the router, but the arduino does not see anything coming from the router.

I wired the rx and tx pins from the router together, ran two ssh windows and did this

window# 1

cat /dev/tts/1

window # 2

echo "test" /dev/tts/1

Test shows up in window 1, which tells me that the router is sending and receiving serial data correctly. It HAS to be something in my code. Here is what i am using now:

Code: [Select]
// include the SoftwareSerial library so you can use its functions:
#include <NewSoftSerial.h>
#include <ctype.h>

#define rxPin 8
#define txPin 9
#define ledPin 13

NewSoftSerial mySerial(8,9);
int inByte;         // incoming serial byte


#define bit9600Delay 84
#define halfBit9600Delay 42
#define bit4800Delay 188
#define halfBit4800Delay 94

int serialChar; // stores character of serial Input as integer
int serialLoop; // counter for serial read loop



unsigned long decay; // counter from last command
unsigned long decaylimit=100000; // 100,000 is about 5 seconds


void setup() {
    // define pin modes for tx, rx, led pins:

  pinMode(ledPin, OUTPUT);
  // set the data rate for the SoftwareSerial port
  mySerial.begin(115200);
  mySerial.println("Hello"); // For debugging purposes
 

  //left/right motors
  pinMode(4, OUTPUT);
  pinMode(5, OUTPUT);
  pinMode(6, OUTPUT);
  pinMode(7, OUTPUT);
  //end debugging
}

int SWread()
{
  byte val = 0;
  while (digitalRead(rxPin));
  //wait for start bit
  if (digitalRead(rxPin) == LOW) {
    delayMicroseconds(halfBit9600Delay);
    for (int offset = 0; offset < 8; offset++) {
     delayMicroseconds(bit9600Delay);
     val |= digitalRead(rxPin) << offset;
    }
    //wait for stop bit + extra
    delayMicroseconds(bit9600Delay);
    delayMicroseconds(bit9600Delay);
    return val;
  }
}
void loop() {
  //check for serial communications
{

  if (mySerial.available()) {
      Serial.println((char)inByte);
//      Serial.print((char)mySerial.read());
     inByte = mySerial.read();
     if ((char)inByte == '1'){
       digitalWrite(13, HIGH);   // set the LED on
       mySerial.println("Light is On");
     }
     if ((char)inByte == '0'){
       digitalWrite(13, LOW);   // set the LED off
       mySerial.println("Light is Off");
     }

    // decay counts the age of the last command
    // at the limit (100,000 = ~5 seconds, all signals are shut off
    if (decay > decaylimit) {
      digitalWrite(4, LOW); digitalWrite(5, LOW); digitalWrite(6, LOW); digitalWrite(7, LOW);
      // stop counting at limit, shut off all pins
    }
    else {
      decay++;
    }

    // this loop read whole strings. as soon as a string is detected
    // each character is evaluated. We only care about the first one.
    for (serialLoop=0; serialLoop < 16 && Serial.available(); serialLoop++) {
      serialChar = Serial.read();

      // echo for debugging only:
      mySerial.print(serialChar);

      // only do evaluation on the first letter (first loop)
      if (serialLoop==0) {

        // serialChar contains the ASCII code of the *first* character sent over serial when defined as int
        switch (serialChar) {

         // logical signals w s a d style any change shuts off previous command       
         case 119: //w - forward, pin 6+8
            digitalWrite(4, LOW); digitalWrite(5, LOW); digitalWrite(6, LOW); digitalWrite(7, LOW);
            digitalWrite(4, HIGH);
            digitalWrite(6, HIGH);           
            decay=0;           
            break;
         case 115: //s - backwards, pin 7+9
            digitalWrite(4, LOW); digitalWrite(5, LOW); digitalWrite(6, LOW); digitalWrite(7, LOW);
            digitalWrite(5, HIGH);
            digitalWrite(7, HIGH);           
            decay=0;           
            break;
         case 97: //a - left, pin 6+9
            digitalWrite(4, LOW); digitalWrite(5, LOW); digitalWrite(6, LOW); digitalWrite(7, LOW);
            digitalWrite(4, HIGH);
            digitalWrite(7, HIGH);           
            decay=0;           
            break;
         case 100: //d - right, pin 7+9
            digitalWrite(4, LOW); digitalWrite(5, LOW); digitalWrite(6, LOW); digitalWrite(7, LOW);
            digitalWrite(5, HIGH);
            digitalWrite(6, HIGH);           
            decay=0;           
            break;           
         case 113: //q - stop, pin 6+7+8+9 off
            digitalWrite(4, LOW); digitalWrite(5, LOW); digitalWrite(6, LOW); digitalWrite(7, LOW);
            decay = decaylimit;           

        }
      }
    }
  }
}
}




PaulS

Quote
It HAS to be something in my code.

Possibly. But, for code that determines whether the Arduino can send data, or receive data, that code is WAY to complex.

Try something much simpler that blinks an LED when data is received, and sends that data back out.

Until what comes in makes sense, developing complex code to use that data doesn't make sense.

Unplug the motors, and put them back in the box. Remove all code for manipulating the motors.

Get rid of unused functions.

Code: [Select]
      Serial.println((char)inByte);
     inByte = mySerial.read();

Is the Arduino supposed to be clairvoyant? Print a character, then read it.

Code: [Select]
    for (serialLoop=0; serialLoop < 16 && Serial.available(); serialLoop++) {
What is the significance of looping 16 times?

Code: [Select]
         case 119: //w - forward, pin 6+8
Why not:
Code: [Select]
case 'w': // No comment needed

jair2k4

My apologies,

Again, this code was all thrown in together from stuff i have found on the net. I am a novice when it comes to both linux and processing. I really dont know what to do or how to modify the code from this point forward... to be quite honest, i am amazed that i got this far.

I dont know how to manipulate the other code, but as for the cases, i believe they mean that if the arduino receives that number, then it needs to turn on or off the pins specified (as they are the pins that go out to the motor controller). Changing it to 'w' would mean that when 'w' is sent, the pins must be written high or low. The signal being sent from the car server app on the router is sending these specific numbers. If i change that, it will break everything.

I removed the comments, as they were a carry over from the code i copied from. Could you possibly help modify the code with the necessary changes? Any way to print in whatever is received from the router into the serial console in the arduino software? Thats what ive been working on for 2 days, which is why i'm getting so frustrated. I cant even do something as simple as that. Remember, I think the case functions have to stay the way they are.

Code: [Select]
// include the SoftwareSerial library so you can use its functions:
#include <NewSoftSerial.h>
#include <ctype.h>

#define rxPin 8
#define txPin 9
#define ledPin 13

NewSoftSerial mySerial(8,9);
int inByte;         // incoming serial byte


#define bit9600Delay 84
#define halfBit9600Delay 42
#define bit4800Delay 188
#define halfBit4800Delay 94

int serialChar; // stores character of serial Input as integer
int serialLoop; // counter for serial read loop



unsigned long decay; // counter from last command
unsigned long decaylimit=100000; // 100,000 is about 5 seconds


void setup() {
    // define pin modes for tx, rx, led pins:

  pinMode(ledPin, OUTPUT);
  // set the data rate for the SoftwareSerial port
  mySerial.begin(115200);
  mySerial.println("Hello"); // For debugging purposes
 

  //left/right motors
  pinMode(4, OUTPUT);
  pinMode(5, OUTPUT);
  pinMode(6, OUTPUT);
  pinMode(7, OUTPUT);
  //end debugging
}

int SWread()
{
  byte val = 0;
  while (digitalRead(rxPin));
  //wait for start bit
  if (digitalRead(rxPin) == LOW) {
    delayMicroseconds(halfBit9600Delay);
    for (int offset = 0; offset < 8; offset++) {
     delayMicroseconds(bit9600Delay);
     val |= digitalRead(rxPin) << offset;
    }
    //wait for stop bit + extra
    delayMicroseconds(bit9600Delay);
    delayMicroseconds(bit9600Delay);
    return val;
  }
}
void loop() {
  //check for serial communications
{

  if (mySerial.available()) {
      Serial.println((char)inByte);
//      Serial.print((char)mySerial.read());
     inByte = mySerial.read();
     if ((char)inByte == '1'){
       digitalWrite(13, HIGH);   // set the LED on
       mySerial.println("Light is On");
     }
     if ((char)inByte == '0'){
       digitalWrite(13, LOW);   // set the LED off
       mySerial.println("Light is Off");
     }

    // decay counts the age of the last command
    // at the limit (100,000 = ~5 seconds, all signals are shut off
    if (decay > decaylimit) {
      digitalWrite(4, LOW); digitalWrite(5, LOW); digitalWrite(6, LOW); digitalWrite(7, LOW);
      // stop counting at limit, shut off all pins
    }
    else {
      decay++;
    }

    // this loop read whole strings. as soon as a string is detected
    // each character is evaluated. We only care about the first one.
    for (serialLoop=0; serialLoop < 16 && Serial.available(); serialLoop++) {
      serialChar = Serial.read();

      // echo for debugging only:
      mySerial.print(serialChar);

      // only do evaluation on the first letter (first loop)
      if (serialLoop==0) {

        // serialChar contains the ASCII code of the *first* character sent over serial when defined as int
        switch (serialChar) {

         // logical signals w s a d style any change shuts off previous command       
         case 119:
            digitalWrite(4, LOW); digitalWrite(5, LOW); digitalWrite(6, LOW); digitalWrite(7, LOW);
            digitalWrite(4, HIGH);
            digitalWrite(6, HIGH);           
            decay=0;           
            break;
         case 115:
            digitalWrite(4, LOW); digitalWrite(5, LOW); digitalWrite(6, LOW); digitalWrite(7, LOW);
            digitalWrite(5, HIGH);
            digitalWrite(7, HIGH);           
            decay=0;           
            break;
         case 97:
            digitalWrite(4, LOW); digitalWrite(5, LOW); digitalWrite(6, LOW); digitalWrite(7, LOW);
            digitalWrite(4, HIGH);
            digitalWrite(7, HIGH);           
            decay=0;           
            break;
         case 100:
            digitalWrite(4, LOW); digitalWrite(5, LOW); digitalWrite(6, LOW); digitalWrite(7, LOW);
            digitalWrite(5, HIGH);
            digitalWrite(6, HIGH);           
            decay=0;           
            break;           
         case 113: //q - stop, pin 6+7+8+9 off
            digitalWrite(4, LOW); digitalWrite(5, LOW); digitalWrite(6, LOW); digitalWrite(7, LOW);
            decay = decaylimit;           

        }
      }
    }
  }
}
}




Graynomad

Quote
I think the case functions have to stay the way they are.

Why is that?

119 = 'w'
115 = 's'
97 = 'a'
100 = 'd'
113 = 'q'

so as PaulS said

Code: [Select]
case 119:

is the same as

Code: [Select]
case 'w':

Why make life difficult? He wasn't suggesting that you just remove the comments, but that if the code was written correctly you wouldn't need them in the first place.

But that's by the by until you can prove the basic hardware works, once again, as PaulS said

Quote
Try something much simpler that blinks an LED when data is received, and sends that data back out.


Put that code aside for the moment and use small easily tested steps to build up to the final result.

______
Rob
Rob Gray aka the GRAYnomad www.robgray.com

jair2k4

#6
Nov 28, 2011, 04:11 am Last Edit: Nov 28, 2011, 04:21 am by jair2k4 Reason: 1
Cant stress this enough.... very limited knowledge of processing. You might say im a complete idiot.

Now here is the part where you all start flaming me... does anyone have anything already written that can do this? I can build a freaking robot but i cant write a simple code. Shows you my level of expertise.

I'm researching and trying to learn this as i type this very message, but until i find an answer.... help please?

EDIT:

Just tried this and it didnt work.....

Code: [Select]
#include <LED.h>
#include <NewSoftSerial.h>
#define rxPin 8
#define txPin 9

NewSoftSerial mySerial(8,9);
int inByte;         // incoming serial byte

#define bit9600Delay 84
#define halfBit9600Delay 42
#define bit4800Delay 188
#define halfBit4800Delay 94

LED led = LED(13);   // the pin that the LED is attached to

void setup() {
   mySerial.begin(115200);
  mySerial.println("Hello"); // For debugging purposes
  led.blink(250, 2);}  // initialize serial communication:

void loop()
{
  int numMails = 0;

  delay(2000);

  switch (Serial.available()) {
    /* Serial.available() is the number of bytes waiting.  Convert from
     * ASCII val to an int.  Intentional switch-case fall through below.
     */
    case 3:
numMails = Serial.read();
numMails -= 48;
numMails *= 10;
    case 2:
numMails += Serial.read();
numMails -= 48;
numMails *= 10;
    case 1:
numMails += Serial.read();
numMails -= 48;
break;
    default:
/* If >3 chars, just clear out the incoming buffer. */
while (Serial.available())
  Serial.read();
return;

  }
led.blink(400, numMails);
}


PaulS

Code: [Select]
  switch (Serial.available()) {
Serial data transmission is ssslllooowww. You might send 3 bytes at once, but only one might have arrived by the time this code is executed.

So, you treat the number of emails as though the sender sent a 1 digit number.

Quote
Just tried this and it didnt work.....

Yes, it did. It might not have produced the results you wanted, but the code did something. You need to describe what it did, and what you expected it to do.

I'd strongly suggest that you dump whatever it is that is sending data to the Arduino until you are CERTAIN that the Arduino is reading serial data correctly, and producing the correct output based on the serial data that it receives.

Send the Arduino data using the Serial Monitor, and have the Arduino send data back to the Serial Monitor.

When the Arduino reacts properly to the serial data, while sending data back, comment out the calls to send data back, to make sure that the time taken to send the data is not affecting the processing of the data being sent to the Arduino.

When the Arduino produces accurate results without echoing any data, then you can return to your current data source, and work out whether the Arduino is getting data, separate from whether it is processing that data correctly.

Quote
very limited knowledge of processing.

What does knowledge of Processing have to do with anything? Surely you haven't figured out how to run Processing on the router have you?

Instead of trying to debug Processing, wifi, the router, the level shifter and a bunch of other stuff at once, break the problem down into testable pieces.

jair2k4

I expected it to blink an led on the arduino (pin 13) when serial data was sent. It did not.

As for knowledge of processing.... The best I can do is take someone else's code and strip it down to suit my needs. I cant write my own stuff from scratch. I havent been able to do that with a programming language since HTML 5.0 came out. heh. I know how people hate it when someone comes in here and goes "waaaaa. write my code for me!" which is why I am not asking you to do so. I am trying to learn how to do this myself by reverse engineering others's codes, but it is backfiring in my face. With this type of coding, if i miss one small thing, i screw everything up.

I dont even know how to get it to loop a code around. when i type something in the serial monitor, it doesnt come back in. I think I had it working using the really basic serial code from the wiki. One thing i can say for certain. I am trashing newsoftserial. I havent been able to get it to work at all. no matter what i do. I was using it and SoftwareSerial because someone told me there might be an issue with communication because my router and arduino might both be using the UART, but i do not think this is the case. Can anyone confirm this part? If i can just go back to using hardware serial knowing for certain that it should work, that would be a great deal of stress off of my shoulders there.

Paul, you tell me to dump anything that is coming out to the arduino until i am sure that it is working properly. That is all i am trying to do actually. If i could get my router to dump a simple "hello world" to my serial monitor at this point, i think i would jump 12 feet in the air. What code would i call to make this happen?

Graynomad and Paul, you have both been very understanding so far and so i hope you dont take this wrong, but any help with a viable test sketch you can give me would help IMMENSELY. I would be able to dissect it and learn it, which would probably tell me all i need to know about how to get these two to talk together. Remember, i am not asking you to write my project for me. I am just deferring to the experts here. I know when I am beaten, and i think i bit off more than i could chew on this particular project. But with the countless hours i have dumped into it, it is too late to abandon it at this point.

Thank you again, and i hope you done flame me for being a noob.

jair2k4

Sorry for the double post, but i have been waiting all day hoping someone will lend a hand. Does anyone have some code or can make some code that will flash a led any time serial data is received and then print it into the arduino serial monitor?

Graynomad

This might get you started,

Code: [Select]

#define LEDpin 13

void setup () {

Serial.begin(115200);
Serial1.begin(4800);

pinMode(LEDpin, OUTPUT);

}

void loop () {
static byte c;

if (Serial1.available() > 0) {
c = Serial1.read();
Serial.println (c, HEX);
digitalWrite (LEDpin, HIGH);
delay (100);
digitalWrite (LEDpin, LOW);
delay (100);
}

}



It will miss a lot of characters because of the delay()s but you should see something.

______
Rob
Rob Gray aka the GRAYnomad www.robgray.com

jair2k4

#11
Nov 29, 2011, 05:32 am Last Edit: Nov 29, 2011, 05:44 am by jair2k4 Reason: 1
Thanks Graynomad. Isn't Serial1 only for the mega though? will this still work if i remove the 1 from everything?

Edit: I tried it without the second serial port and removed the '1' after Serial and it flashes whenever i input text from the console, but not when i have the bot hooked up... Hrmm. baud rates are all ok. What am I doing wrong? Should i set up swserial and read on that port and send on a different one?

Code: [Select]
#define LEDpin 13

void setup () {

Serial.begin(115200);


pinMode(LEDpin, OUTPUT);

}

void loop () {
static byte c;

if (Serial.available() > 0) {
c = Serial.read();
Serial.println (c, HEX);
digitalWrite (LEDpin, HIGH);
delay (100);
digitalWrite (LEDpin, LOW);
delay (100);
}

}

Graynomad

Ok for some reason I thought you had a Mega.

Quote
will this still work if i remove the 1 from everything?

No, you'll have to use newSoftSerial. Just replace all the Serial1 stuff with NSS equivalents.

______
Rob


Rob Gray aka the GRAYnomad www.robgray.com

jair2k4

ok check this out and tell me is i messed up. When i send through the console, the light flashes, but no green flickering to indicate that it is receiving.

Am i supposed to be sending on serial and receiving on newsoftserial?

Code: [Select]
#include <NewSoftSerial.h>
#define LEDpin 13
#define txPin 9

NewSoftSerial mySerial(8,9);
void setup () {

Serial.begin(115200);
mySerial.begin(9600);

pinMode(LEDpin, OUTPUT);

}

void loop () {
static byte c;

if (mySerial.available() > 0) {
c = mySerial.read();
Serial.println (c, HEX);
digitalWrite (LEDpin, HIGH);
delay (100);
digitalWrite (LEDpin, LOW);
delay (100);
}

}

Graynomad

#14
Nov 29, 2011, 06:09 am Last Edit: Nov 29, 2011, 06:11 am by Graynomad Reason: 1
Quote
Am i supposed to be sending on serial and receiving on newsoftserial?

Yes.

Quote
When i send through the console,

You're not sending through the console, the code receives from the NSS Rx pin (9?) and sends to the PC. You should see characters on the console.

______
Rob
Rob Gray aka the GRAYnomad www.robgray.com

Go Up