Прерывания в Ардуино через Serial

annshorn
Offline
Зарегистрирован: 28.01.2020

Добрый день, у меня есть код, связывающий ардуино и датчиком gy-521:

#include<Wire.h>
const int MPU=0x68; 
int16_t AcX,AcY,AcZ;
unsigned long time;

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(){
  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);
  
}

Дальше я связываю ардуино и питоном, и обрабатываю полученные данные уже в питоне.

 with serial.Serial('/dev/tty.usbmodem143101', 19200, timeout = 1) as ser:
_____value = ser.readline() 
_____value = value.decode('utf-8', 'ignore')
...сохраняю значения в массив...
ser.close()
 //закрываю порт

Существует проблема: после N-итераций обработки (периодически вызываю функцию считывания) данные с ардуино перестают приходить (приходит пустая строка)

Мне подсказали, что проблема в том, что нет прерывания. Соотвественно мой вопрос: как правильно написать (и куда вставить) функцию прерывания по пришедшему символу?

я думала сделать так:

#include<Wire.h>
const int MPU=0x68; 
int16_t AcX,AcY,AcZ;
unsigned long time;

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(){
  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);

  if (Serial.available())  {
    char incom = Serial.read()
    // ???????
  }
  
}

но что писать вместо "????"

 

rkit
Offline
Зарегистрирован: 23.11.2016

Прерывание по пришедшему символу в ардуино есть всегда. Код со стороны питона очень странный. Порт не надо постоянно открывать и закрывать. И синхронизации какой-то нет, если открылись посередине строки, то получится мусор.

nik182
Offline
Зарегистрирован: 04.05.2015

Проблема не в ардуине. Попробуйте просто в терминальную программу вывод. Он останавливается? 

annshorn
Offline
Зарегистрирован: 28.01.2020

 

rkit пишет:

Прерывание по пришедшему символу в ардуино есть всегда. Код со стороны питона очень странный. Порт не надо постоянно открывать и закрывать. И синхронизации какой-то нет, если открылись посередине строки, то получится мусор.

 

1) оно может быть и есть,но меня интересует, чтобы он перестал считывать данные

2) код странный, потому что это последний костыль, которым я пыталась избежать проблему считывания пустой строки. до этого я один раз только открывала порт

3) синхронизация есть дальше по коду в питоне, то есть я обхожу все данные, которые меня не устраивают

annshorn
Offline
Зарегистрирован: 28.01.2020

nik182 пишет:

Проблема не в ардуине. Попробуйте просто в терминальную программу вывод. Он останавливается? 

 

я не очень поняла, про что вы

annshorn
Offline
Зарегистрирован: 28.01.2020
вот код для питона, если что
​
​        with serial.Serial('/dev/tty.usbmodem143101', 19200, timeout = 1) as ser:
            time.sleep(5) 
            while i < self.time_observation: 
                value = ser.readline()
                value = value.decode('utf-8', 'ignore')
                if value == '': #если данных нет
                    print('empty')
                    self.sensors() #перезапустить функцию
                v = value.rstrip().replace(" ", "") #разделить данные и тд и тп
                result = [x.strip() for x in v.split(',')]

                if len(result) == 4: #интересуют только "целые" строчки
                    if i == 0:
                        try:
                            self.time_start = float(result[0])
                        except ValueError:
                            print('error:', result[0])
                            pass
                    try:
                        array_105_x.append(float(result[1]))
                        array_105_y.append(float(result[2]))
                        array_105_z.append(float(result[3]))
                        i+=1 
                        pbar.update(1)
                    except ValueError:
                        print(result)
                        continue
            #ser.write(str(1).encode())
            #print ("RECIEVED BACK:",ser.readline().decode())
            pbar.close()
        ser.close()  

 

 

annshorn
Offline
Зарегистрирован: 28.01.2020

я попыталась сделать методом тру-фолс, но оно не работает) то есть данные сначала НЕ считываются, стоит отправить "0": беспрерывный поток данных

#include<Wire.h>
const int MPU=0x68; 
int16_t AcX,AcY,AcZ;
unsigned long time;
bool allow = false;

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 == true){
    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);
  }
  
}

void serialEvent() {
  while (Serial.available()){
    char incom = Serial.read();
    Serial.print(incom);
    if (incom == 0){
      allow = false;
    }
    else {
      allow = true;
    }
  }
}

 

mixail844
Offline
Зарегистрирован: 30.04.2012
вам посоветовали , в сообщении #2 : скачайте уже готовый терминал ,на выбор : 
или 
или на ваш вкус
 
и посмотрите,перестанут ли в них приходить данные,так поймете проблема на стороне ардуино или на стороне пайтона
nik182
Offline
Зарегистрирован: 04.05.2015

И даже в родной ардуиновский терминал. Если нажать на кнопку монитор порта в правом верхнем углу ИДЕ, то весь вывод принта будет выводится в это окно. Если вывод программы идет без пустых строк - проблема в принимающей стороне. Если много раз открывать - закрывать порт, он в конце концов глюкает.    

annshorn
Offline
Зарегистрирован: 28.01.2020

в ардуино все работает без проблем, в питоне - если принимать беспрерывно данные - тоже

я сейчас переписала код, теперь он работает в порте ардуино (по 1 - считывает данные, по 0 - нет), то есть реально происходит прерывание.

#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){
    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.println("Allow:");Serial.print(incom);Serial.print("///");
    Serial.print(time);Serial.print(",");Serial.print(AcX);Serial.print(",");Serial.print(AcY);Serial.print(",");Serial.println(AcZ); 
    delay(0);
  }
  
}

void serialEvent() {
  while (Serial.available()){
    int incom = Serial.read() - '0';
    //delay(10);
    Serial.println(incom);
    if (incom == 0){
      allow = false;
      delay(100);
    }
    if (incom == 1){
      allow = true;
      delay(100);
    }
  }
}

 

теперь уже реально проблема в принимающей стороне. потому что не удается отослать команды:

Если инициализировать все сначала

arduino_port_sensor = serial.Serial('/dev/tty.usbmodem143101', 19200, timeout = 1)
arduino_port_sensor.write(str(0).encode())
time.sleep(6)
msg = arduino_port_sensor.read(arduino_port_sensor.inWaiting())
print(msg)
 
то есть я отсылаю в ардуино 0 -- данные не считываются (как и должно быть)
 
затем отправляю 1 - то есть считываю данные
arduino_port_sensor.write(str(1).encode())
("RECIEVED BACK:",arduino_port_sensor.readline().decode())
данные считываются и все ок.
 
но если затем отправить снова "0":
arduino_port_sensor.write(str(0).encode())
то он не прекращает отсылать данные :(
 
хотя в самой ардуино все работает.