2016-11-23 6 views
0

У меня есть приложение, где мне нужно:Синхронизация между Python и Arduino с использованием последовательной связи

  1. движение серводвигателем с помощью Arduino в положение и остановки в этом положении
  2. иметь камеру под контролем питона приобретают изображение в этой позиции
  3. когда изображение приобретается, сервопривод должен переместиться в симметричном положении

последовательность повторяется несколько N времени

Итак, я попытался синхронизировать arduino и код python с помощью последовательной связи. На стороне arduino, когда сервопривод достигает позиции, он отправляет строку в код python, используя последовательную связь. Строка является либо «Крест», либо «Со» в зависимости от достигнутого положения. Ардуино должен дождаться, когда строка «Ok» будет отправлена ​​последовательной связью с помощью кода python (после получения изображения). После получения этой строки ардуино должно приводить в действие сервопривод, чтобы он переместился в другое положение.

На стороне Python кода, я прочитал последовательные данные и в зависимости от строки, полученные (Cross или Co):

  1. имя строка определяется
  2. Изображение приобретается с помощью камеры
  3. изображение сохраняется или добавляется в список
  4. Строка «Ok» отправляется в arduino.

коды прилагаются ниже.

Проблема в том, что мне не удается правильно синхронизировать положения сервопривода и получение изображения. Сервопривод просто запускается между двумя позициями и, похоже, не читает ни одной строки из последовательной связи. Это никогда не останавливается на самом деле. Однако код arduino отправляет «Cross» и «Co» в код python, и код python позволяет читать и получать и сохранять изображения, но часто с неправильными именами. Наличие кода arduino достаточно долго для каждой позиции не является решением, так как мне нужна приличная частота получения изображения.
Итак, я хотел бы знать, что является лучшим способом синхронизации двух кодов и быть уверенным, что правильное имя моих изображений будет соответствовать правильному положению сервопривода?

Заранее благодарим за любые ссылки или идеи.

Грег

Arduino код `

#include <Servo.h> 

//servo 
Servo myservo; // create servo object to control a servo 
// twelve servo objects can be created on most boards 
int pos = 0; // variable to store the servo position 

//camera 
const int CameraPin = 53;  // the number of the camera trigg 
int CameraState = LOW;    // ledState used to set the LED 
const int ledPin = 13;  // the number of the LED pin 
String Str = "c"; 

void setup() { 
    myservo.attach(9); // attaches the servo on pin 9 to the servo object 
    // set the digital LED pin as output: 
    pinMode(CameraPin, OUTPUT); 
    // set the digital camera pin as output: 
    pinMode(ledPin, OUTPUT); 
    //serial communication 
    Serial.begin(9600); 
    Serial.println("Ready"); 
     } 
void loop() { 

Serial.flush(); 
// go to Co position and wait 
ServoCo(15); // go to Co position 
Serial.println("Co"); //send signal Co to python 
while(!Serial.available()) {} // wait for python to send data acquired 
while ((Serial.available()<2)) // Test on the length of the serial string 
{ 
    delay(1); 
    String Str = Serial.readStringUntil('\n'); 
    Serial.println(Str); 
} 

// go to cross position and wait 
ServoCross(15); // go to Cross position 
Serial.println("Cross"); 
while(!Serial.available()) {} 
    while ((Serial.available()<2)) 
{ 
    delay(1); 
    String Str = Serial.readStringUntil('\n'); 
    Serial.println(Str); 
} 
} 
delay(100); 
} 

void ServoCross(int ServoDelay) 
{ 
    for (pos = 105; pos >= 75; pos -= 1) { // goes from 0 degrees to 180 degrees 
    // in steps of 1 degree 
    myservo.write(pos);    // tell servo to go to position in variable 'pos' 
    delay(ServoDelay); 
    } 
} 
    void ServoCo(int ServoDelay) 
{ 
    for (pos = 75; pos <= 105; pos += 1) 
    { // goes from 0 degrees to 180 degrees 
    // in steps of 1 degree 
    myservo.write(pos);    // tell servo to go to position in variable 'pos' 
    delay(ServoDelay); 
    }` 

Python код:

from time import sleep 
import serial 
import scipy 
ser = serial.Serial('COM10', 9600) # Establish the connection on a specific port 

Nb_total_image = 100 
imagergb_cross = np.zeros((480,640)) 
imagergb_co = np.zeros((480,640)) 
counter_image = 0; 

ser.write('start') 
while counter_image<Nb_total_image: 
    ser.flush() 
    ReadArduino = ser.readline().split('\r')[0] # Read the newest output from the Arduino 

    print(ReadArduino) 
    if ReadArduino == 'Cross': 
     nameImage = 'CrossImage' + str(counterImageCross) 
     cam.reset_frame_ready()     # reset frame ready flag 
     # send hardware trigger OR call cam.send_trigger() here 
     cam.send_trigger() 
     cam.wait_til_frame_ready(1000)    # wait for frame ready due to trigger   
     imageRawcross = cam.get_image_data() 
     ser.write("Ok\n") 

    else: 
     nameImage = 'CoImage' + str(counterImageCo) 
     cam.reset_frame_ready()     # reset frame ready flag 
     # send hardware trigger OR call cam.send_trigger() here 
     cam.send_trigger() 
     cam.wait_til_frame_ready(1000)    # wait for frame ready due to trigger     
     ImageRawCo = cam.get_image_data() 
     ser.write("Ok\n") 
    imagergb = imageRawCo-imageRawcross 
    counter_image = counter_image + 1 
+0

Передает ли Arduino принимаемый 'Ok' назад? –

+0

'Serial.available() <2' будет true, если в буфере имеется один байт. 'Ok \ n' - три байта. И вы никогда не очищаете буфер, читая его. –

+0

Да, я хотел, чтобы код ожидал в цикле while, пока есть только 2 байта, и переходит, когда есть три (например, с «Ok \ n»). Когда вы говорите, очистите буфер, вы имеете в виду флеш-память? – gregory

ответ

0

В вашей loop() функции вы реализовали свое программное обеспечение в этой функции будет выполняться один раз, как main() в программном обеспечении консоли.

Поскольку Arduino (C языке сайт) имеет связь через последовательный канал связи с компьютером (Python) языком сайт, один эффективное решением является использование государства машины принципов.

Шаг 1 - определить список состояний, необходимых, а также количество позиций для достижения.

Простой enum e_State позволяет определить список.

typedef enum e_State { 
    STATE_START = 0, // first state to initialize 
    STATE_MOVE_POS, // moving Servo to the selected position 
    STATE_SEND_CMD, // sending message when position reached 
    STATE_WAIT_ACK // waiting acknowledge from message 
} eState; 

Для 2 позиции, чтобы достичь, enum e_Pos используется:

typedef enum e_Pos { 
    FIRST_POS = 0, 
    SECOND_POS 
} ePos; 

Шаг 2 - определить исходные параметры

Для того, чтобы хранить постоянные данные betwee п loop() вызовов, static переменных используются:

static eState LoopState = STATE_START; // to store the current state 
static ePos ServoPos = FIRST_POS; // to store the selected position 

И хранить во время следующего состояния, добавьте eState NextState.

При входе функции loop(), NextState = LoopState; на поддерживать одинаковое состояние по умолчанию.

Этап 3 - определение алгоритма состояния машины.

void loop() { 

static eState LoopState = STATE_START; // to store the current state 
static ePos ServoPos = FIRST_POS; // to store the selected position 

    eState NextState = LoopState; 

    switch (LoopState) { 
    case STATE_START: 
     ServoPos = FIRST_POS; 
     NextState = STATE_MOVE_POS; 
     break; 
    case STATE_MOVE_POS: 
     NextState = STATE_SEND_CMD; 
     break; 
    case STATE_SEND_CMD: 
     NextState = STATE_WAIT_ACK; 
     break; 
    case STATE_WAIT_ACK: 
     // NextState = STATE_MOVE_POS; 
     break; 
    default: 
     // when undefined state, restart 
     NextState = STATE_START; 
    } 
    // define the state for the next loop 
    LoopState = NextState; 
} 

Шаг 4 - управлять действием STATE_MOVE_POS с выбранным ServoPos.

switch (ServoPos) { 
case FIRST_POS: 
    ServoCo(15); // go to 'Co' position 
    break; 
case SECOND_POS: 
    ServoCross(15); // go to 'Cross' position 
    break; 
}; 
NextState = STATE_SEND_CMD; // when reached, send serial message 

Шаг 5 - управлять действием STATE_SEND_CMD на основе достигнутой ServoPos.

Serial.flush(); // clear the serial buffer 
if (ServoPos == FIRST_POS) { 
    Serial.println("Co"); //send signal 'Co' to python 
} 
else { 
    Serial.println("Cross"); //send signal 'Cross' to python 
} 
NextState = STATE_WAIT_ACK; 

Шаг 6 - управлять действием STATE_WAIT_ACK путем поиска "OK" признать.

При необходимости добавьте сравнение if (Str == "OK"), чтобы убедиться, что компьютер отвечает правильно.

if (Serial.available()) { // no state change while no acknowledge 
    String Str = Serial.readStringUntil('\n'); 
    Serial.println(Str); 
    if (Str == "OK") { 
     // ack is OK, select the next position and continue 
     ServoPos = (ServoPos == FIRST_POS)?(SECOND_POS):(FIRST_POS); 
     NextState = STATE_MOVE_POS; 
    } 
    else { 
     // ack is KO, restart from first position 
     NextState = STATE_START; 
    } 
} 
+0

Хорошо спасибо. Это не так. – gregory