首页 文章

Raspberry Pi和Arduino之间的简单双向串行通信

提问于
浏览
1

我想在我的Raspberry Pi和我的Arduino之间进行简单的双向串行通信 . 这是一个项目,我将用另一个我还没有的串行设备替换Arduino .

我已经完成了从Arduino到Raspberry Pi的单向通信(https://maker.pro/raspberry-pi/tutorial/how-to-connect-and-interface-raspberry-pi-with-arduino),但我在使用双向时遇到了一些麻烦 . 我使用的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()'添加到字节后进行编码 . 没有错误,但没有发生/正在写出来 .

这样做的目的是让Raspberry Pi向Arduino发送'3',并向Arduino发送'我收到的响应:3',它应该在Raspberry Pi / Python的终端窗口中打印出来 . 从那里我想我可以使我的目标更复杂,发送这样的命令:'0 30 50 100'我没有的设备会响应 .

我感谢任何帮助 . 谢谢 .

1 回答

  • 0

    在我的项目中,我的目标是通过串行接口 Build Arduino和Raspberry Pi之间的双向数据交换 . Raspberry Pi发送Arduino命令执行,Arduino发送Raspberry Pi传感器读数(当前是随机数) .

    目前,该项目包括两个用于Raspberry Pi的脚本,用Python编写,以及一个Arduino程序 . 使用URWID库的Raspberry Pi的第一个脚本组织图形界面和命令输入,第二个脚本用于与串行端口通信 . 来源如下 . 操作的结果非常令人满意,但也许某个地方我做错了什么?这个问题的解决方案是否正确?

    Arduino software:

    #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 = ' ';
        }
      }
    }
    

    Python GUI script

    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 = 'S - 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()
    

    Python communication script

    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
    

相关问题