Go Down

Topic: reading Arduino serial port on raspberry pi (Read 468 times) previous topic - next topic

nagdrn

Hi everyone!
I am sensing electric current of 8 brushless motors using the ACS711 and the Arduino Pro Mini (each motor has it own current sensor).
so far on the serial monitor I am getting the expected signals.
To record the output data to a file on a Raspberry Pi 3, I am using serial connection.
My Arduino is detected on the ttyUSB0 port.
at the beginning of the file, random characters i.e ^@^@^@  are printed as shown below:
^@
^@^@^@-0.25 ; 0.36 ; 0.52 ; 0.31 ; 0.17 ; 0.62 ; 0.26 ; 0.19
-0.25 ; 0.36 ; 0.52 ; 0.31 ; 0.17 ; 0.62 ; 0.26 ; 0.19
-0.25 ; 0.36 ; 0.52 ; 0.31 ; 0.17 ; 0.62 ; 0.26 ; 0.19

Although I used the function memset() to initialize my char buffer, it won't change anything.

my sketch is shown below, and my c code that I use to read serial port and write data into file is attached.

Please guys I need your help.

thank you very much.

short ec[8][80];
float ec_avg[8];
byte curr_idx = 0;
int i,j;

void setup()
{
  Serial.begin(9600, SERIAL_8N1);

  for (j = 0; j < 80 ; j++)
  {
    for (i = 0; i < 8 ; i++)
    {
      ec[j] = 0;
      ec[j] = analogRead(i);
    }
    delay(100);
  }

 
}

void loop()
{
  for (i = 0; i < 8; i++) {
    ec[curr_idx] = analogRead(i);
    ec_avg = 0;
  }
  curr_idx++;
  curr_idx = curr_idx % 80;

  for (i = 0; i < 8 ; i++)
    for (j = 0; j < 80; j++)
      ec_avg += ec[j];

  for (i = 0; i < 8 ; i++)
  {
    Serial.print( currentSensor(  ec_avg / 80.0 )  ); // averaging, converting to current, and printing
    if (i < 7)
      Serial.print(" ; ");
  }
 
  Serial.println(" ");
  delay(100);
}

long readInternalVcc() {

  long result;
  ADMUX = _BV(REFS0) | _BV(MUX3) | _BV(MUX2) | _BV(MUX1);
  delay(2);                                                    // Wait for Vref to settle
  ADCSRA |= _BV(ADSC);                                         // Convert
  while (bit_is_set(ADCSRA, ADSC));
  result = ADCL;
  result |= ADCH << 8;
  result = 1126400L / result;                                  // Back-calculate AVcc in mV
  return result;
}

float currentSensor(float RawADC) {

  int    Sensitivity    = 45; // mV/A
  long   InternalVcc    = readInternalVcc();
  double ZeroCurrentVcc = InternalVcc / 2;
  double SensedVoltage  = (RawADC * InternalVcc) / 1024;
  double Difference     = SensedVoltage - ZeroCurrentVcc;
  double SensedCurrent  = Difference / Sensitivity;
  return SensedCurrent;                                        // Return the Current
}

MarkT

You have some nulls at the start, this may simply be line noise stored by the serial driver from before you connected anything - there is probably an ioctl() call on the serial device for sorting this out.
Also it might be that the Pro Mini doesn't have pull-ups on RX/TX to default the serial lines to idle
state, so they could just be floating during Arduino bootup.
[ I will NOT respond to personal messages, I WILL delete them, use the forum please ]

pert

Please use code tags (</> button on the toolbar) when you post code or warning/error messages. The reason is that the forum software can interpret parts of your code as markup, leading to confusion, wasted time, and a reduced chance for you to get help with your problem. This will also make it easier to read your code and to copy it to the IDE or editor. Using code tags and other important information is explained in the How to use this forum post. Please read it.

When connecting output from a 5 V Arduino to a Pi you need to consider the possibility that could damage the Pi, which uses 3.3 V IO. There are 3.3 V Pro Minis so I'm not sure if that's an issue for you or if you are already converting the level.

PaulS

You could have the Arduino send some known string, like "Ready!" as the first thing it sends, to tell the Pi that it should now use the data it gets from the Arduino.
The art of getting good answers lies in asking good questions.

nagdrn

#4
Mar 08, 2017, 07:43 am Last Edit: Mar 08, 2017, 07:55 am by nagdrn
Hi guys!
Thank you very much for your feedback. After opening the output file using bvi, I found NULL characters.
as I could not figure out how to use ioctl(), I solved the issue by testing if the first byte of my buffer contains a NULL, if so ignore, if not write down the data.
any opinions on this solution?

my apologies for not quoting my code before.

Code: [Select]
while ((ret_in = read(input_fd, buffer, sizeof(buffer))) > 0)
    {
        if (buffer[0] != 0)
            ret_out = write(output_fd, buffer, ret_in);
    }

Chagrin

Still kinda flimsy. I'd suggest an initialization process like Paul described, although instead of "Ready!" I think "ATA" is the proper string to use ;)

Kinda weak on my Hayes command set these days.

nagdrn

Thank you all!
I am a bit confused with regard to Paul and Chagrin initialization process.
to send string, do you mean something like serial.write("Ready");
are Ready or ATA special commands of Arduino?
could you please elaborate more?
Cheers

PaulS

Quote
do you mean something like serial.write("Ready");
Code: [Select]
Serial.print("Ready!");
The art of getting good answers lies in asking good questions.

nagdrn

Thank you PaulS.
I added an instruction to send a string after opening the serial port. however I still have an issue.
when running my c code from RPi to record electric current data coming from Arduino using serial usb, I end up having incomplete data sequences at the beginning and the end of the file as shown below:

40,6.33
4.38,6.24,4.95,6.59,4.58,6.18,3.89,6.17
4.37,6.28,4.97,6.58,4.55,6.16,3.93,6.19
​​4.30,6.22,4.97,6.55,4.55,6.18,3.95,6.22
4.25,6.20,4.98,6.62,4.57,6.26,4.00,6.29
4.28,6.19,4.97,6.66,4.6

I think serial port is holding data from previous execution, also due to the system call signal() when i send CTRL+C signal the code doesn't have time to write the whole buffer.
 
I would like to use '\r' or '\n' characters to detect the send of a sequence and beginning of the next one to write down the data.

Can you guys help me do it, i am really lost!
I would like to ignore any sequence that is incomplete.

here is the c code section responsible of recording data.

Please feel free to add your comments.

Thank you guys!


Code: [Select]
/* Copy process */

    while ((ret_in = read(input_fd, buffer, sizeof(buffer))) > 0)

    {
        if (buffer[0] != 0)
        {
            ret_out = write(output_fd, buffer, ret_in);
            if (SIGINT == a)
            {
                printf("Coming out of the loop after getting Interruption signal CTRL+C\n");
                break;
            }
        }

    }

Go Up