0

Arduino code:

this code is provided communication between sensor gy-521 and arduino. I read data by the command "1", after 1000 samples arduino is waited for new command for read data.

Arduino code works well in arduino port.

#include<Wire.h>
const int MPU=0x68; 
int16_t AcX,AcY,AcZ;
unsigned long time;
bool allow = false;
//int incom = 0;
void setup(){
 Wire.begin();
 Wire.beginTransmission(MPU);
 Wire.write(0x6B); 
 Wire.write(0); 
 Wire.endTransmission(true);
 Serial.begin(19200);
 while (!Serial);// wait for serial port to connect. Needed for native USB port only
}
void loop(){
 if (allow){ //if allow == true, read data
 for (int i = 0; i < 1000; i++){
 Wire.beginTransmission(MPU);
 Wire.write(0x3B); 
 Wire.endTransmission(false);
 Wire.requestFrom(MPU,12,true); 
 AcX=Wire.read()<<8|Wire.read(); 
 AcY=Wire.read()<<8|Wire.read(); 
 AcZ=Wire.read()<<8|Wire.read();
 time = millis();
 Serial.print(time);Serial.print(",");Serial.print(AcX);Serial.print(",");Serial.print(AcY);Serial.print(",");Serial.println(AcZ); 
 delay(0);
 }
 Serial.println(0); //see UPD.3
 allow = false;
 } 
}
void serialEvent() {
 while (Serial.available()){ //wait for command
 int incom = Serial.read() - '0'; 
 Serial.println(incom);
 if (incom == 0){ //if 0 - stop 
 allow = false;
 delay(100);
 }
 if (incom == 1){ //if 1 - read data
 allow = true;
 delay(100);
 }
 }
}

Python code:

 def sensors(self):
 self.arduino_port_sensor.reset_input_buffer() #clear buffer
 self.arduino_port_sensor.write(str(1).encode()) #send command to arduino - read data
 main_array = []
 pbar = tqdm(total=self.time_observation) #just to see the progress
 while True:
 values = self.arduino_port_sensor.readline().decode().rstrip().replace(" ", "") #read data, some manipulation for cleaning
 main_array.append(values)
 pbar.update(1)
 if values == '': #if data is empty
 print('!!!!')
 continue
 if values == '0': #see UPD.3
 break
 pbar.close()
 ...bla bla...

I call this function time to time, then in some step, arduino stops sending data -- it sends empty string.

It looks like:

PS. In this code I use 2 ports: for sensor and for motor, 2 different arduino. The principe of working second arduino with motor the same, but it works without any problem (I just send command with "action" to arduino with motor, and then receive answer "received back")

enter image description here

Question: what's wrong with python? how to fix this problem?


UPD

Initialization:

arduino_port_sensor = serial.Serial('/dev/tty.usbmodem143101', 19200, timeout = 1)

UPD.2

It receive command - "1" - read data, the interruption occurs while reading data:

enter image description here

UPD.3

Also i changed the code of arduino -- added the "0" after loop.

UPD.4

If I recall this function after arduno stopped sending data, I get this:

enter image description here

asked Jan 30, 2020 at 14:40
6
  • How did you initialize the PySerial? Your python code doesn't show that. Commented Jan 30, 2020 at 19:11
  • There can be different issues: 1. Are you sure Arduino is sending something? For example, when you say you stopped getting gata, check if the TX LED on the Arduino board is blinking or not. 2. Did Arduino actually receive "1" before you stopped getting data? 3. What's the timeout of the PySerial? Are you trying to read faster than Arduino can provide? Commented Jan 30, 2020 at 19:34
  • 0) I added initialization 1) yes, because it works some iterations (the most long work about 39 iterations). My program wont work if arduino not sending data. 2) yes, I checked this. Before getting data I always have "1" in the beggining. 3) timeout = 1, btw how it can work in some iterations and not working after? Commented Jan 30, 2020 at 20:22
  • 1) What I actually meant, WHEN it stopped working, it can be either your Python or the Arduino. It worked for 39 iterations. So Arduino was sending data during those 39 iterations. But when it stopped working, is it because of Arduino is not sending anymore or 'for some reason' Python is not able to read it. One way to verify is, check the Tx LED on the Arduino board WHEN your system stopped working. If the LED still blinks as it was, when the system was working, then we know for sure its the Python we need to fix. Commented Jan 30, 2020 at 23:51
  • 2) Same for this too, did you receive '1' in the Arduino right before it stopped working? One way to check this is when it stops working print the main_array. If main_array doesn't have '1', that means your Arduino never sent '1' i.e. it never received '1'. Commented Jan 30, 2020 at 23:56

1 Answer 1

1

There can be different reasons for your issue. But from the update you added later, we can at least say that your Arduino sometimes doesn't receive the character "1". And when that happens, your Python gets stuck in the infinite loop of trying to read something from the serial port.

As your Arduino responds with "1" when it receives "1", you can base your application on that i.e. if Arduino doesn't respond with "1", keep sending "1".

I wrote a sample program based on your code. I removed the "Wire" part in the Arduino code as I don't have your sensor. I would urge you to test with this Arduino code to make sure that Your sensor is not blocking your Arduino. Wire read can be blocked forever depending on the IC you are trying to read (and if you don't have a timeout).

int16_t AcX,AcY,AcZ;
unsigned long time;
bool allow = false;
void setup()
{
 Serial.begin(19200);
}
void loop()
{
 if (allow) //if allow == true, read data
 {
 for(int i = 0; i < 10; i++)
 {
 AcX = 1; 
 AcY = 2; 
 AcZ = 3;
 time = millis();
 Serial.print(time); Serial.print(",");
 Serial.print(AcX); Serial.print(",");
 Serial.print(AcY); Serial.print(",");
 Serial.println(AcZ); 
 }
 Serial.println('0');
 allow = false;
 } 
}
void serialEvent() 
{
 while (Serial.available()) //wait for command
 {
 int incom = Serial.read() - '0'; 
 Serial.println(incom);
 if (incom == 0) //if 0 - stop 
 {
 allow = false;
 delay(100);
 }
 if (incom == 1) //if 1 - read data
 {
 allow = true;
 delay(100);
 }
 }
}

In the Python code, I checked if I received "1" from Arduino. If not I kept trying.

import serial
import time
def sensors():
 # Clear receive buffer
 arduino_port_sensor.reset_input_buffer() 
 while True:
 # Send command to arduino to send data
 arduino_port_sensor.write('1'.encode())
 # As arduino send LF and CR at the end, let's strip those from the end
 response = arduino_port_sensor.readline().rstrip(b'\r\n ').decode()
 # Arduino should respond with the cmd that it received, 
 # if not, send cmd again
 if response == '1':
 # Arduino acknowledged
 break
 else:
 print('Did not receive 1. Retrying...')
 main_array = []
 while True:
 values = arduino_port_sensor.readline().rstrip(b'\r\n ').decode()
 if values == '':
 print('!!!!')
 # This should never happen, but if it does happen, try to read again
 continue
 elif values == '0':
 # print(main_array)
 # We are done receiveing packets
 break
 else:
 # We are still receiving packets
 main_array.append(values)
arduino_port_sensor = serial.Serial('COM50', 19200, timeout=3)
# Let PySerial get ready
time.sleep(3)
while True:
 sensors()
 time.sleep(1)
answered Jan 31, 2020 at 23:26

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.