【问题标题】:Simple 2-way serial communication between Raspberry Pi and ArduinoRaspberry Pi 和 Arduino 之间的简单 2 路串行通信
【发布时间】:2018-07-31 15:10:37
【问题描述】:

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

我已经完成了从 Arduino 到 Raspberry Pi 的单向通信 (https://maker.pro/raspberry-pi/tutorial/how-to-connect-and-interface-raspberry-pi-with-arduino),但是在使用 2-way 时遇到了一点麻烦。我使用的 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',我没有的设备会响应。

感谢您的帮助。谢谢。

【问题讨论】:

  • 尝试在ser.write 行之后添加延迟
  • 到目前为止,您只显示了 RasPi 代码。但是需要两个人沟通。因此,了解 Arduino 的功能也很重要。 Arduino 如何读取 RasPi 发送给它的内容?它是否在等待 RasPi 未发送的终结符(\r\n)?
  • Arduino 代码取自 Arduino 网站链接的示例。
  • 所以,我添加了延迟,但仍然没有任何反应。

标签: python arduino raspberry-pi


【解决方案1】:

我迟到了,但我希望这对其他人有所帮助。 我试图进行双向通信,我可以从双方发送和接收字符串数据,这就是我所做的:-
Arduino方面:-

void setup() {
   Serial.begin(9600); // begin transmission
}
void loop() {
  String val;
  while (Serial.available() > 0) {
    val = val + (char)Serial.read(); // read data byte by byte and store it
  }
  Serial.print(val); // send the received data back to raspberry pi
}

在覆盆子方面我有(python):-

import serial
port = "/dev/ttyACM0"#put your port here
baudrate = 9600
ser = serial.Serial(port, baudrate)
def tell(msg):
    msg = msg + '\n'
    x = msg.encode('ascii') # encode n send
    ser.write(x)

def hear():
    msg = ser.read_until() # read until a new line
    mystring = msg.decode('ascii')  # decode n return 
    return mystring

while True:
    val = input() # take user input
    tell(val) # send it to arduino
    var = hear() # listen to arduino
    print(var) #print what arduino sent

我希望很清楚 Arduino 从树莓派收到消息并将同样的信息发送回 Arduino。同样,你可以用它做一些其他的事情。

【讨论】:

    【解决方案2】:

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

    目前,该项目包括两个用 Python 编写的 Raspberry Pi 脚本和一个 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 = ' ';
        }
      }
    }
    

    Python GUI 脚本

    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 通信脚本

    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
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-05-27
      • 2019-09-01
      • 2018-04-16
      • 1970-01-01
      相关资源
      最近更新 更多