Pages: [1] 2   Go Down
Author Topic: Two way serial communication with raspberry Pi (radio project)  (Read 4034 times)
0 Members and 1 Guest are viewing this topic.
0
Offline Offline
Newbie
*
Karma: 0
Posts: 45
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Hi everybody,

I installed "music player deamon" (mpd, mpc) on my new rasberry pi. I created a playlist that contains the urls of some internet radio stations. I "tune" the stations by turning a potentiometer's knob, connected to my Arduino.

This is done using the "map" function: the pot's range is divided by the number of stations which are in my playlist. (The number of stations is initially set in variable "maxNumb". So the pot delivers values between 1 and 26)

The station number that mpc has to play is transfered via serial communication; on raspberry this value is read by a bash script that controls mpc. That works fine and stable:

Code:
int sensorValue = analogRead(A0);
    delay(100);
    int upperValue = sensorValue + 2;
    int lowerValue = sensorValue - 2;
  } while (sensorValue < upperValue && sensorValue > lowerValue);
  int tunerValue = map(sensorValue, 0, 1023, 1, maxNumb);
 
  if (tunerValue < 10)
  {
    Serial.print(0);
  }
 
  Serial.println(tunerValue,DEC);

Now to my problem:

If I add more stations I want to automatically change the value of variable "maxNumb", so that all stations can be addressed using the potentiometer.

Rasperry sends the number of stations that are on the playlist to Arduino via the serial interface:

Code:
echo "$NUMBEROFSTATIONS" > /dev/ttyACM0

The transfered number is between 20 and 99. If arduino receives this new value, variable "maxNumb" should change and the new stations should be selectable with the pod.

I try to receive this value with the following code (works well on arduino's serial monitor, but not together with raspberry):

Code:
if (Serial.available())
{
  char ch = Serial.read();
    if(index <  MaxChars && ch >= '0' && ch <= '9'){
      strValue[index++] = ch; // add the ASCII character to the string;
    }
    else
    {
      // here when buffer full or on the first non digit
      strValue[index] = 0;        // terminate the string with a 0
      maxNumb = atoi(strValue);  // use atoi to convert the string to an int
      index = 0;
    }
  }

Any ideas, why this works on the serial console but not when the data comes from the computer?

Schwabinger




Logged

Manchester (England England)
Offline Offline
Brattain Member
*****
Karma: 598
Posts: 33328
Solder is electric glue
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Is the computer sending a terminating character after the numbers in the string?
Logged

0
Offline Offline
Newbie
*
Karma: 0
Posts: 45
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Hi,

I tried the following to transmit the value "40" with no success:

echo 40 > /dev/ttyACM0
echo "40" > /dev/ttyACM0
echo 40\n > /dev/ttyACM0
echo "40\n" > /dev/ttyACM0
echo 40\\n > /dev/ttyACM0
echo "40\\n" > /dev/ttyACM0

Kind regards,

Schwabinger

Logged

Manchester (England England)
Offline Offline
Brattain Member
*****
Karma: 598
Posts: 33328
Solder is electric glue
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

So what do you recieve from the Pi? Print out the ASCII of what you recieve.
Logged

0
Offline Offline
Newbie
*
Karma: 0
Posts: 45
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

I turn the pot all the way to the right side ... so after sending the value 40, variable maxNumb should get that value and arduino should send this value back to the computer - but this does not happen:


Code:
root@raspberrypi:/home/pi# cat /dev/ttyACM0
26

26

26

26

26 is the value that was initially set to the varable "maxNumb" in my sketch.

Here is the code of whole sketch:

Code:
/*
 *
 * Siehe Arduino Cookbook: safari books onlin
 * Uebertraegt Sendernummer zum Radio
 */
const int MaxChars = 2;
char strValue[MaxChars+1];
int index = 0;
int maxNumb = 26 ;
int value;
int upperValue;
int lowerValue;
char ch;

void setup()                    // run once, when the sketch starts
{
  Serial.begin(9600);           // set up Serial library at 9600 bps
}

void loop()                       // run over and over again
{
  int sensorValue = analogRead(A0);

do
  { 
int sensorValue = analogRead(A0);
    delay(100);
    int upperValue = sensorValue + 2;
    int lowerValue = sensorValue - 2;
  } while (sensorValue < upperValue && sensorValue > lowerValue);
  int tunerValue = map(sensorValue, 0, 1023, 1, maxNumb);
 
  if (tunerValue < 10)
  {
    Serial.print(0);
  }
 
  Serial.println(tunerValue,DEC);

delay(250);

if (Serial.available())
{
  char ch = Serial.read();
    if(index <  MaxChars && ch >= '0' && ch <= '9'){
      strValue[index++] = ch; // add the ASCII character to the string;
    }
    else
    {
      // here when buffer full or on the first non digit
      strValue[index] = 0;        // terminate the string with a 0
      maxNumb = atoi(strValue);  // use atoi to convert the string to an int
      index = 0;
    }
  }

}


Logged

Manchester (England England)
Offline Offline
Brattain Member
*****
Karma: 598
Posts: 33328
Solder is electric glue
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Very bad code that, see the comments for this first fragment:-
Code:
void loop()                       // run over and over again
{
  int sensorValue = analogRead(A0); // this value is never used so why take it?

do
  { 
int sensorValue = analogRead(A0);  // this creates a new and different instance of the variable each time it is run.
                                                    // this means that you are filling your stack with useless variables which will eventually crash the system
    delay(100); // why? it is doing nothing for anything

Logged

0
Offline Offline
Newbie
*
Karma: 0
Posts: 45
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Tried to change as advised - problem still exists ...:

Code:
/*
 *
 * Siehe Arduino Cookbook: safari books online
 * Sends station numbers to Raspberri: ok
 * Receives max Numb of stations from Raspberry: nok
 */
const int MaxChars = 2;
char strValue[MaxChars+1];
int index = 0;
int maxNumb = 26 ;
int value;
int upperValue;
int lowerValue;
char ch;
int poti = 0;
int sensorValue;


void setup()                    // run once, when the sketch starts
{
  Serial.begin(9600);           // set up Serial library at 9600 bps

}

void loop()                       // run over and over again
{
 
do
  { 
sensorValue = analogRead(poti);
    int upperValue = sensorValue + 2;
    int lowerValue = sensorValue - 2;
  } while (sensorValue < upperValue && sensorValue > lowerValue);
  int tunerValue = map(sensorValue, 0, 1023, 1, maxNumb);
  if (tunerValue < 10)
  {
    Serial.print(0);
  }
 
  Serial.println(tunerValue,DEC);

delay(250);

if (Serial.available())
{
  char ch = Serial.read();
    if(index <  MaxChars && ch >= '0' && ch <= '9'){
      strValue[index++] = ch; // add the ASCII character to the string;
    }
    else
    {
      // here when buffer full or on the first non digit
      strValue[index] = 0;        // terminate the string with a 0
      maxNumb = atoi(strValue);  // use atoi to convert the string to an int
      index = 0;
    }
  }

}

Logged

Manchester (England England)
Offline Offline
Brattain Member
*****
Karma: 598
Posts: 33328
Solder is electric glue
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Quote
Tried to change as advised - problem still exists ...:
Of course it will, we have not got over the silly mistakes you are making. You have to do that first before we can begin to sort out your logic.

PLEASE PLEASE PLEASE   STOP creating variables inside loops.
Logged

0
Offline Offline
God Member
*****
Karma: 39
Posts: 988
Get Bitlash: http://bitlash.net
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

I wonder if the bootloader is eating your data.

Immediately after the serial port is opened, the Arduino spends about 1500ms in the bootloader waiting to see if you are about to upload a new sketch.

During this time, any serial output sent from the PC side is interpreted by the bootloader, not your program.  Mostly, it is ignored.  Just like what you are seeing.

The unix 'echo' command opens the port and writes to it right away.  This works fine on the serial monitor, but because of the bootloader problem it won't work on arduino.

If this reasoning is sound, you need a little program to open the serial port and wait a couple seconds before sending the playlist length, rather than using 'echo'.

-br

Edit: Another way, besides waiting a fixed time, is to wait for a character string from the arduino to signal 'ready'.  Bitlash, for example, sends '\n> ' as a prompt when it's ready.  You can see this at work in the bloader.js program, which uploads files to Arduino over the serial port:

https://github.com/billroy/bloader.js/blob/master/bloader.js

« Last Edit: December 02, 2012, 08:06:34 am by billroy » Logged

Manchester (England England)
Offline Offline
Brattain Member
*****
Karma: 598
Posts: 33328
Solder is electric glue
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Quote
The unix 'echo' command opens the port and writes to it right away.
If the arduino is connected through the serial GPIO pins this is not important.
However, if it is connected through the USB port this will cause the arduino to reset on opening AND on closing.
However you have to eliminate the rubbish arduino code first.
Logged

Seattle, WA USA
Offline Offline
Brattain Member
*****
Karma: 601
Posts: 48543
Seattle, WA USA
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Code:
int upperValue;
int lowerValue;
char ch;
int poti = 0;
int sensorValue;
Some nice global variables...

Code:
do
  { 
sensorValue = analogRead(poti);
    int upperValue = sensorValue + 2;
    int lowerValue = sensorValue - 2;
One global variable and two new local variables...

Code:
  } while (sensorValue < upperValue && sensorValue > lowerValue);
These names refer to the GLOBAL variables.

OP: You REALLY need to learn about scope.
Logged

0
Offline Offline
Newbie
*
Karma: 0
Posts: 45
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Thanks to everyone who is helping here ..:-)

Ardunio and computer are connected via USB.

Tried to take all variables out of the loop. Resulted in code that compiles ... but if I run it in the serial console nothing happens any more. The  WHILE condition will never be true, so I will remove that.

Code:
*
 *
 * Siehe Arduino Cookbook: safari books online
 * Sends station numbers to Raspberri: ok
 * Receives max Numb of stations from Raspberry: nok
 */
const int MaxChars = 2;
char strValue[MaxChars+1];
int index = 0;
int maxNumb = 26;
int upperValue;
int lowerValue;
char ch;
int poti = 0;
int sensorValue = 1;
int tunerValue = 1;


void setup()                    // run once, when the sketch starts
{
  Serial.begin(9600);           // set up Serial library at 9600 bps
}

void loop()                       // run over and over again
{
 
do
  {  
sensorValue = analogRead(poti);
    upperValue = sensorValue + 2;
    lowerValue = sensorValue - 2;
  } while (sensorValue < upperValue && sensorValue > lowerValue);
  tunerValue = map(sensorValue, 0, 1023, 1, maxNumb);
  if (tunerValue < 10)
  {
    Serial.print(0);
  }
  
  Serial.println(tunerValue,DEC);

delay(250);

if (Serial.available())
{
  char ch = Serial.read();
    if(index <  MaxChars && ch >= '0' && ch <= '9'){
      strValue[index++] = ch; // add the ASCII character to the string;
    }
    else
    {
      // here when buffer full or on the first non digit
      strValue[index] = 0;        // terminate the string with a 0
      maxNumb = atoi(strValue);  // use atoi to convert the string to an int
      index = 0;
    }
  }

}
« Last Edit: December 02, 2012, 09:03:38 am by Schwabinger » Logged

Seattle, WA USA
Offline Offline
Brattain Member
*****
Karma: 601
Posts: 48543
Seattle, WA USA
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Quote
Tried to take all variables out of the loop. Resulted in code that compiles ... but if I run it in the serial console nothing happens any more. The  WHILE condition will never be true, so I will remove that.
All that you needed to remove was the int keyword that defined a new variable. Without the int keyword, the name refers to the existing, global, instance.
Logged

0
Offline Offline
Newbie
*
Karma: 0
Posts: 45
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

I removed some lines that are not used at the moment anyway:


Code:
/*
 *
 * Siehe Arduino Cookbook: safari books online
 * Sends station numbers to Raspberri: ok
 * Receives max Numb of stations from Raspberry: nok
 */
const int MaxChars = 2;
char strValue[MaxChars+1];
int index = 0;
int maxNumb = 26;
int upperValue;
int lowerValue;
char ch;
int poti = 0;
int sensorValue = 10;
int tunerValue = 1;

void setup()                    // run once, when the sketch starts
{
  Serial.begin(9600);           // set up Serial library at 9600 bps
}

void loop()                       // run over and over again
{
 sensorValue = analogRead(poti);

 tunerValue = map(sensorValue, 0, 1023, 1, maxNumb);
 
  Serial.println(tunerValue,DEC);

delay(250);

if (Serial.available())
{
  char ch = Serial.read();
    if(index <  MaxChars && ch >= '0' && ch <= '9'){
      strValue[index++] = ch; // add the ASCII character to the string;
    }
    else
    {
      // here when buffer full or on the first non digit
      strValue[index] = 0;        // terminate the string with a 0
      maxNumb = atoi(strValue);  // use atoi to convert the string to an int
      index = 0;
    }
  }

}

At least at the built in serial console it does what I want it to do:

- Starting with an initial value for the variable "maxNumb" (26) depending on the poti's position a number between 1 and 26 ist transfered via serial;
- If I enter a different value in the console, maxNumb is updated; if for instance I enter 50, by turning the knob I can produce numbers between 1 and 50:

But I still have the problem, that I cannot use "echo" from my computer to fill this variable.
-
Logged

Seattle, WA USA
Offline Offline
Brattain Member
*****
Karma: 601
Posts: 48543
Seattle, WA USA
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Quote
But I still have the problem, that I cannot use "echo" from my computer to fill this variable.
Why not? There is no debug stuff in the code that reads from the serial port. If you are using the Serial Monitor to see the Arduino output, try typing the value in the text field and hitting the send icon. If you are using some other method to see the serial output, describe that method.

Logged

Pages: [1] 2   Go Up
Jump to: