繁体   English   中英

Raspberry Pi与Arduino之间的简单2路串行通信

[英]Simple 2-way serial communication between Raspberry Pi and Arduino

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

我已经完成了从Arduino到Raspberry Pi的单向通信( https://maker.pro/raspberry-pi/tutorial/how-to-connect-and-interface-raspberry-pi-with-arduino ),但是在使用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()',以便对字节进行编码。 没有错误出现,但是没有任何反应/正在被写出。

Raspberry Pi的目标是向Arduino发送“ 3”,而Arduino则以“我收到:3”作为响应,该信息应打印在Raspberry Pi / Python的终端窗口中。 从那里,我可以想象我可以使它更复杂,以实现发送如下命令的目标:“ 0 30 50 100”,我没有的设备会响应。

感谢您的帮助。 谢谢。

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

当前,该项目包括两个用Python编写的Raspberry Pi脚本和一个Arduino程序。 使用URWID库的Raspberry Pi的第一个脚本用于组织图形界面和命令输入,第二个脚本用于与串行端口通信。 资料来源如下。 手术的结果是令人满意的,但是也许在我做某事的地方? 这个问题的解决方案正确吗?

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

我答复您很晚,但我希望这会对其他人有所帮助。 我试图进行双向通信,可以从双方发送和接收字符串数据,这就是我所做的:
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。 同样,您可以使用它进行其他操作。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM