Простая двусторонняя последовательная связь между Raspberry Pi и Arduino

1

Я хочу сделать простой двухсторонний последовательный обмен между моей малиной Pi и моим Arduino. Это для проекта, в котором я заменил Arduino другим серийным устройством, которого у меня пока нет.

Я сделал одностороннюю связь (https://maker.pro/raspberry-pi/tutorial/how-to-connect-and-interface-raspberry-pi-with-arduino) от Arduino до малины Pi, но у меня есть небольшая проблема с 2-сторонним движением. Код Arduino, который я использую, приведен в этом примере: https://www.arduino.cc/en/Serial/Read:

int incomingByte = 0;   // for incoming serial data

void setup() {
        Serial.begin(9600);     // opens serial port, sets data rate to 9600 bps
}

void loop() {

        // send data only when you receive data:
        if (Serial.available() > 0) {
                // read the incoming byte:
                incomingByte = Serial.read();

                // say what you got:
                Serial.print("I received: ");
                Serial.println(incomingByte, DEC);
        }
}

И код Python, который я использую, таков:

import serial
import time
ser = serial.Serial('/dev/ttyACM1',9600)
var1 = "3"
while True:
    ser.write(var1.encode())
    time.sleep(0.2)
    read_serial=ser.readline()
    print read_serial

Просматривая сеть, я изменил значение, которое нужно отправить из только ser.write('3') в строку 'var1' и поместить '.encode()' после этого, чтобы кодировать в байты. Ошибок не возникает, но ничего не происходит/выписывается.

Целью этого является то, что малина Pi отправит "3" в Arduino и Arduino, чтобы ответить "Я получил: 3", который должен быть напечатан в окне терминала Raspberry Pi/Python. Оттуда я предполагаю, что я могу сделать это более сложным по отношению к моей цели отправки команды следующим образом: "0 30 50 100", на которое устройство, на которое у меня нет, будет отвечать.

Я ценю любую помощь. Спасибо.

  • 0
    Попробуйте добавить задержку после строки ser.write
  • 0
    Вы показали только код RasPi. Однако для общения нужны двое. Поэтому также важно знать, что делает Arduino. Как Arduino читает то, что ему посылает RasPi? Ожидает ли он терминатор (возможно, \r или \n ), который RasPi не отправляет?
Показать ещё 2 комментария
Теги:
arduino
raspberry-pi

1 ответ

0

В моем проекте моя цель - установить двусторонний обмен данными между Arduino и Raspberry Pi через последовательный интерфейс. Малина Pi отправляет команду Arduino для выполнения, Arduino отправляет показания датчика малины Pi (в настоящее время случайное число).

В настоящее время проект включает два сценария для малины Pi, написанные на Python, и программу для Arduino. Первый скрипт для Raspberry Pi с использованием библиотеки URWID организует графический интерфейс и ввод команды, второй скрипт используется для связи с последовательным портом. Источники приведены ниже. Результат операции вполне удовлетворительный, но, может быть, где-то я делаю что-то неправильно? Правильно ли это решение проблемы?

Программное обеспечение Arduino:

#define SERIAL_SPEED 19200 // the speed of the serial port
#define READ_SENSOR_INTERVAL 1000UL  // frequency of output to the serial port 

int IN1 = 7; 
int IN2 = 6;
int IN3 = 5;
int IN4 = 4;
int ENA = 9;
int ENB = 3;

char command     = 'S';
char prevCommand = 'A';
int velocity = (4 + 1) * 10 + 100; // the fill factor of the PWM

unsigned long timer0 = 2000; 
unsigned long timer1 = 0;    

long randNumber;
long myflag = 0;

void setup() {
  Serial.begin(SERIAL_SPEED);
  pinMode (ENA, OUTPUT);
  pinMode (IN1, OUTPUT);
  pinMode (IN2, OUTPUT);
  pinMode (ENB, OUTPUT);
  pinMode (IN4, OUTPUT);
  pinMode (IN3, OUTPUT);
}

void loop()
{
  static unsigned long prevSensorTime = 0;
  if (millis() - prevSensorTime > READ_SENSOR_INTERVAL) {
    prevSensorTime = millis();
    if (myflag == 1)
    {
      randNumber = random(300);
      Serial.print(command);
      Serial.println(randNumber);
    }
  }


  if (Serial.available() > 0) {
    timer1 = millis();
    prevCommand = command;
    command = Serial.read();
    myflag = 1;
    if (command != prevCommand) {
      switch (command) {
        case 'W':
          // Вперёд
          analogWrite(ENA, 0);
          analogWrite(ENB, 0);
          delay(20);
          digitalWrite (IN2, LOW);
          digitalWrite (IN1, HIGH);
          digitalWrite (IN4, LOW);
          digitalWrite (IN3, HIGH);
          analogWrite(ENA, velocity);
          analogWrite(ENB, velocity);

          break;
        case 'A':
          analogWrite(ENA, 0);
          analogWrite(ENB, 0);
          delay(20);
          digitalWrite (IN2, LOW);
          digitalWrite (IN1, HIGH);
          digitalWrite (IN4, HIGH);
          digitalWrite (IN3, LOW);
          analogWrite(ENA, velocity);
          analogWrite(ENB, velocity);
          break;
        case 'S':
          analogWrite(ENA, 0);
          analogWrite(ENB, 0);
          delay(20);
          digitalWrite (IN2, HIGH);
          digitalWrite (IN1, LOW);
          digitalWrite (IN4, HIGH);
          digitalWrite (IN3, LOW);

          analogWrite(ENA, velocity);
          analogWrite(ENB, velocity);
          break;
        case 'D':
          analogWrite(ENA, 0);
          analogWrite(ENB, 0);
          delay(20);
          // A
          digitalWrite (IN2, HIGH);
          digitalWrite (IN1, LOW);
          // B
          digitalWrite (IN4, LOW);
          digitalWrite (IN3, HIGH);
          analogWrite(ENA, velocity);
          analogWrite(ENB, velocity);
          break;
        case ' ': 
          //velocity = 0;
          analogWrite(ENA, 0);
          analogWrite(ENB, 0);
          break;
        default:  
          if ((command >= 48) && (command <= 57)) {
            if (command == 48)
            {
              velocity = 0;
            }
            else
            {
              velocity = (command - 48 + 1) * 10 + 100;
            }
          }
      }
    } 
  }
  else {
    timer0 = millis();  // Получение текущего времени
    if ((unsigned long)(timer0 - timer1) > 20000) {
      analogWrite(ENA, 0);
      analogWrite(ENB, 0);
      prevCommand = ' ';
    }
  }
}

Сценарий GUI Python

from __future__ import print_function, absolute_import, division
import subprocess
import urwid
import serial
from subprocess import Popen, PIPE
from time import sleep


def exit_on_q(key):
    global power
    global ser
    global spower
    global p
    global currc

    if key in ('q', 'Q'):
        p.stdin.write(b'Q\n')
        p.stdin.flush()
        sleep(1)
        raise urwid.ExitMainLoop()


    if key in ('w', 'W'):
    # forward
        currc = 'W - Forward'
        p.stdin.write(b'W\n')
        p.stdin.flush()

    if key in ('a', 'A'):
    # Left
        currc = 'A - Left'
        p.stdin.write(b'A\n')
        p.stdin.flush()

    if key in ('s', 'S'):
    # Backward
        currc =  - Backward'
        p.stdin.write(b'S\n')
        p.stdin.flush()

    if key in ('d', 'D'):
    # Right
        currc = 'D - Right'
        p.stdin.write(b'D\n')
        p.stdin.flush()


    if key in (' '):
    # Stop
        currc = 'Space - Stop'
        p.stdin.write(b' \n')
        p.stdin.flush()

    if key in ('+'):
        if (power < 99):
            power = power + 10 
            spower = spower + 1
            txt_CP.set_text(('banner', str(power)))

    if key in ('-'):
        if (power > 0):
            power = power - 10
            spower = spower - 1
            txt_CP.set_text(('banner', str(power)))

    txt_CCV.set_text(('banner', currc))

def enter_idle():
    loop.remove_watch_file(pipe.stdout)

def update_text(read_data):
    txt_Q.set_text(('banner', read_data))

if __name__ == '__main__':

    currc = "No command"

    palette = [
        ('banner', 'black', 'light gray'),
        ('streak', 'black', 'dark blue'),
        ('bg', 'black', 'dark blue'),]

    # spower = 0..9 (48 .. 57)
    spower = 4
    power = spower * 10

    txt_F = urwid.Text(('banner', u"W - Forward (\u2191)"), align='center')
    txt_LRS = urwid.Text(('banner', u"\u2190 A - Left | Space - Stop | D - Right \u2192"), align='center')
    txt_B = urwid.Text(('banner', u"S - Backward (\u2193)"), align='center')
    txt_P = urwid.Text(('banner', u"'+' Increase motor power | '-' Decrease motor power"), align='center')
    txt_C = urwid.Text(('banner', u"Current power:"), align='center')

    txt_CP = urwid.Text(('banner', str(power)), align='center')

    # current command
    txt_CC = urwid.Text(('banner', u"Current command: "), align='center')
    txt_CCV = urwid.Text(('banner', u"No command"), align='center')

    txt_Log = urwid.Text(('banner', u"Log: "), align='center')
    txt_LogV = urwid.Text(('banner', u""), align='center')

    txt_Q = urwid.Text(('banner', u"Q - Quit"), align='center')

    #empty string
    txt_E = urwid.Text(('banner', u""), align='center')

    pile = urwid.Pile([txt_F, txt_LRS, txt_B, txt_E, txt_P, txt_C, txt_CP, txt_E, txt_CC, txt_CCV, txt_E, txt_Log, txt_LogV, txt_E, txt_Q ])
    top = urwid.Filler(pile, top = 5)


    loop = urwid.MainLoop(top, palette, unhandled_input=exit_on_q, handle_mouse=False)

    stdout = loop.watch_pipe(update_text)
    stderr = loop.watch_pipe(update_text)   
    p = subprocess.Popen(['python3', 'shell_edt.py'], stdin = PIPE, stdout = stdout, stderr = stdout, shell = False)    
    loop.run()

Пиратский скрипт связи

import sys
import threading
import serial
from time import sleep

global currcomm

readtimer = 1 # 


def read():
    global serialport
    global currcomm

    threading.Timer(readtimer, read).start()

    if (currcomm != -1):
        data = serialport.read(10);
        print(str(data) + " : "  + str(len(data)))
        sys.stdout.flush();
        #sleep(0.5)     '''     


serialport = serial.Serial("/dev/ttyACM0", 19200, timeout=0.2)
data = serialport.read(100);


currcomm = -1

threading.Timer(readtimer, read).start()
sleep(1)

while True:
    currcomm = input()

    if (currcomm == 'S') or (currcomm == 'D') or (currcomm == 'W') or (currcomm == 'A') or (currcomm == ' '):
        serialport.write(bytes(currcomm, encoding = 'utf-8'));
    if (currcomm == 'Q'):
        serialport.close() # Only executes once the loop exits

Ещё вопросы

Сообщество Overcoder
Наверх
Меню