maoinu
@maoinu (sato mao)

Are you sure you want to delete the question?

If your question is resolved, you may close it.

Leaving a resolved question undeleted may help others!

We hope you find it useful!

【RaspberryPi/osoyoo picar】pythonでのudp信号が受け取れない

解決したいこと

MCU(LPC1768)とRaspberryPi間でudp通信をしようとしています。
udpで受けた信号をpythonで解釈できていないです。

ミスをしている個所を教えて下さい

発生している問題・エラー

以下の2つのプロフラムを変更して、MCUからのudp信号を受けて、raspberrypiがモーター駆動をするというプログラムを動かそうとしています。

・OSOYOOのpicarのチュートリアル:スマホからの信号をうけて車を動かす。
  https://osoyoo.com/ja/2020/08/01/osoyoo-raspberry-pi-v2-0-car-lesson-4-use-mobile-app-to-control-the-car-with-udp-protocol/
・MCUからudpで信号を送信するプログラムのオリジナル
  https://qiita.com/hbvcg00/items/552fb765530ebea3e4d8

(RTOSから指示をしてRPiでドライブってアホちゃうか?普通逆だろ!っていうのは、ひとまず置いておいてください。こういう勉強中につまずいています、と解釈してください。)

自分で試したこと

現状MCUからRaspberryPiまではデータが飛んできております
以下の通りです

pi@hogehoge:~ $ nc -4lu 192.168.11.5 8888
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA

ただ、これをpythonプログラムで受信しようとするとうまくいかない

pi@hogehoge:~ $ python3 picar-udp-control2.py 
0
0
0


※コードは下に掲載します
※MCUはつなげたままで、udpで「A」という信号をたれ流し続けているはず
※0は無信号を示している。

当然ではありますが教材のオリジナルはスマホから信号を受けるとちゃんと動いております。

以下、オリジナルのスマホアプリから受けたudp信号。
スマホ内のボタンを押すごとに対応したデータを送ってきます。

pi@hogehoge:~ $ nc -4lu 192.168.0.162 8888
AAAAAAAAAAAAAAAAAAAAAAAALLLRRRBBBBB

で、当然ではありますが、ちゃんとオリジナルコードのpythonでも受信しています

pi@hogehoge:~ $ python3 picar-udp-control.py 
0
A
A
A
A
A
A
^Z
[1]+  停止                  python3 picar-udp-control.py
pi@hogehoge:~ $


通信自体はできていると思っているので、私がいじった部分が何かおかしいとは思っています。

なので、以下、ソースコードで関係しそうなところをピックアップします。
何かおかしいところを気が付きましたらご教授ください。

●raspberrypi側のソースコード
私が変更しているのは後半300行目くらいにある部分で、オリジナルだと自機のIPを指定していませんでしたが、ここにNIC(有線)のIPを指定しているだけです。

UDP_IP = "192.168.11.5" ← UDP_IP = ””
UDP_PORT = 8888

ちなみに、ここを、
UDP_IP = "192.168.0.162"
UDP_PORT = 8888

としてスマホをつなげている側のNIC(wifi)を指定した場合はスマホでの動作はうまくいっていました

#  ___   ___  ___  _   _  ___   ___   ____ ___  ____
# / _ \ /___)/ _ \| | | |/ _ \ / _ \ / ___) _ \|    \
# | |_| |___ | |_| | |_| | |_| | |_| ( (__| |_| | | | |
# \___/(___/ \___/ \__  |\___/ \___(_)____)___/|_|_|_|
#                  (____/
# OSOYOO Raspberry Pi V2.0 car lesson 2: Use Mobile APP to control the car with UDP protocol
# tutorial url: https://osoyoo.com/?p=33003

from __future__ import division
import socket
import time
# Import the PCA9685 module.
import Adafruit_PCA9685
import RPi.GPIO as GPIO
# Initialise the PCA9685 using the default address (0x40).
pwm = Adafruit_PCA9685.PCA9685()

# Alternatively specify a different address and/or bus:
#pwm = Adafruit_PCA9685.PCA9685(address=0x41, busnum=2)
high_speed = 4000  # Max pulse length out of 4096
mid_speed = 2000  # Max pulse length out of 4096
low_speed = 1000  # Max pulse length out of 4096
short_delay = 0.1
long_delay = 0.2
extra_long_delay = 0.3

# Set frequency to 60hz, good for servos.
pwm.set_pwm_freq(60)
GPIO.setmode(GPIO.BCM)  # GPIO number  in BCM mode
GPIO.setwarnings(False)
# Set frequency to 60hz, good for servos.

ob_range = 30  # minimum obstacle distance

# define ultrasonic sensor pins
GPIO_TRIGGER = 20
GPIO_ECHO = 21
servo_lft = 500  # ultrasonic sensor facing right
servo_ctr = 300  # ultrasonic sensor facing front
servo_rgt = 150  # ultrasonic sensor facing left

pwm.set_pwm(15, 0, servo_ctr)
time.sleep(3)  # servo facing front for 3s in order to make orientation alignment

# define L298N(Model-Pi motor drive board) GPIO pins
IN1 = 23  # left motor direction pin
IN2 = 24  # left motor direction pin
IN3 = 27  # right motor direction pin
IN4 = 22  # right motor direction pin
ENA = 0  # left motor speed PCA9685 port 0
ENB = 1  # right motor speed PCA9685 port 1
sensor1 = 5  # No.1 sensor from far left
sensor2 = 6  # No.2 sensor from left
sensor3 = 13  # middle sensor
sensor4 = 19  # No.2 sensor from right
sensor5 = 26  # No.1 sensor from far  right
sts1 = 0
sts2 = 0
sts3 = 0
sts4 = 0
sts5 = 0
cur_status = '0'

# Define motor control  pins as output
GPIO.setup(IN1, GPIO.OUT)
GPIO.setup(IN2, GPIO.OUT)
GPIO.setup(IN3, GPIO.OUT)
GPIO.setup(IN4, GPIO.OUT)
GPIO.setup(sensor1, GPIO.IN)
GPIO.setup(sensor2, GPIO.IN)
GPIO.setup(sensor3, GPIO.IN)
GPIO.setup(sensor4, GPIO.IN)
GPIO.setup(sensor5, GPIO.IN)
GPIO.setup(GPIO_TRIGGER, GPIO.OUT)  # Trigger
GPIO.setup(GPIO_ECHO, GPIO.IN)      # Echo
# Set trigger to False (Low)
GPIO.output(GPIO_TRIGGER, False)


def changespeed(speed_left, speed_right):
    pwm.set_pwm(ENA, 0, speed_left)
    pwm.set_pwm(ENB, 0, speed_right)


def stopcar():
    GPIO.output(IN1, GPIO.LOW)
    GPIO.output(IN2, GPIO.LOW)
    GPIO.output(IN3, GPIO.LOW)
    GPIO.output(IN4, GPIO.LOW)
    changespeed(0, 0)


stopcar()


def backward(speed_left, speed_right):
    GPIO.output(IN1, GPIO.HIGH)
    GPIO.output(IN2, GPIO.LOW)
    GPIO.output(IN3, GPIO.HIGH)
    GPIO.output(IN4, GPIO.LOW)
    changespeed(speed_left, speed_right)

    # following two lines can be removed if you want car make continuous movement without pause
    # time.sleep(short_delay)
    # stopcar()


def forward(speed_left, speed_right):
    GPIO.output(IN2, GPIO.HIGH)
    GPIO.output(IN1, GPIO.LOW)
    GPIO.output(IN4, GPIO.HIGH)
    GPIO.output(IN3, GPIO.LOW)
    changespeed(speed_left, speed_right)
    # following two lines can be removed if you want car make continuous movement without pause
    # time.sleep(short_delay)
    # stopcar()


def turnRight(speed_left, speed_right):
    GPIO.output(IN1, GPIO.LOW)
    GPIO.output(IN2, GPIO.HIGH)
    GPIO.output(IN3, GPIO.HIGH)
    GPIO.output(IN4, GPIO.LOW)
    changespeed(speed_left, speed_right)
    # following two lines can be removed if you want car make continuous movement without pause
    # time.sleep(short_delay)
    # stopcar()


def turnLeft(speed_left, speed_right):
    GPIO.output(IN1, GPIO.HIGH)
    GPIO.output(IN2, GPIO.LOW)
    GPIO.output(IN3, GPIO.LOW)
    GPIO.output(IN4, GPIO.HIGH)
    changespeed(speed_left, speed_right)
    # following two lines can be removed if you want car make continuous movement without pause
    # time.sleep(short_delay)
    # stopcar()


def line_tracking():
    sts1 = 0 if GPIO.input(sensor1) else 1
    sts2 = 0 if GPIO.input(sensor2) else 1
    sts3 = 0 if GPIO.input(sensor3) else 1
    sts4 = 0 if GPIO.input(sensor4) else 1
    sts5 = 0 if GPIO.input(sensor5) else 1
    sensorval = ''.join(
        [str(sts1), str(sts2), str(sts3), str(sts4), str(sts5)])
    print(sensorval)

    if sensorval == "10000" or sensorval == "01000" or sensorval == "11000":
        turnLeft(low_speed, mid_speed)  # The black line left, sharp left turn
        time.sleep(long_delay)
        stopcar()
        time.sleep(short_delay)

    if sensorval == "11100" or sensorval == "10100":
        turnLeft(0, high_speed)  # The black line left,  left turn
        time.sleep(long_delay)
        stopcar()
        time.sleep(short_delay)

    if sensorval == "11110" or sensorval == "01100" or sensorval == "10010" or sensorval == "10110" or sensorval == "11010":
        forward(low_speed, mid_speed)  # slight eft turn
        time.sleep(long_delay)
        stopcar()
        time.sleep(short_delay)

    if sensorval == "01110" or sensorval == "01010" or sensorval == "00100" or sensorval == "10001" or sensorval == "10101" or sensorval == "10011" or sensorval == "11101" or sensorval == "10111" or sensorval == "11011" or sensorval == "11001":
        forward(mid_speed, mid_speed)  # slight eft turn
        time.sleep(long_delay)
        stopcar()
        time.sleep(short_delay)

    if sensorval == "00110" or sensorval == "01111" or sensorval == "01001" or sensorval == "01011" or sensorval == "01101":
        forward(mid_speed, low_speed)  # slight right turn
        time.sleep(long_delay)
        stopcar()
        time.sleep(short_delay)

    if sensorval == "00111" or sensorval == "00101":
        forward(high_speed, low_speed)
        # turnRight(high_speed,0) #The black line is  on the Left of the car, need  Left turn
        time.sleep(long_delay)
        stopcar()
        time.sleep(short_delay)

    if sensorval == "00001" or sensorval == "00010" or sensorval == "00011":
        # The black line is  on the Left of the car, need  Left turn
        turnRight(mid_speed, low_speed)
        time.sleep(long_delay)
        stopcar()
        time.sleep(short_delay)

    if sensorval == "11111":
        stopcar()  # The car front touch stop line, need stop

    if sensorval == "00000":
        # The car front touch stop line, need stop
        backward(low_speed, low_speed)
        time.sleep(short_delay)
        stopcar()
        time.sleep(short_delay)


def measure():
    # This function measures a distance
    GPIO.output(GPIO_TRIGGER, True)
    time.sleep(0.00001)
    GPIO.output(GPIO_TRIGGER, False)
    start = time.time()
    while GPIO.input(GPIO_ECHO) == 0:
        start = time.time()
    while GPIO.input(GPIO_ECHO) == 1:
        stop = time.time()
    elapsed = stop-start
    distance = (elapsed * 34300)/2
    return distance


def obstacle_avoid():
    pwm.set_pwm(15, 0, servo_lft)
    time.sleep(0.3)
    distance = measure()
    sts1 = 0 if distance > ob_range else 1

    pwm.set_pwm(15, 0, servo_ctr)
    time.sleep(0.3)
    distance = measure()
    sts2 = 0 if distance > ob_range else 1

    pwm.set_pwm(15, 0, servo_rgt)
    time.sleep(0.3)
    distance = measure()
    sts3 = 0 if distance > ob_range else 1
    sensorval = ''.join([str(sts1), str(sts2), str(sts3)])

    if sensorval == "100":
        print("100 slight right")
        forward(high_speed, mid_speed)  # slight right turn
        time.sleep(long_delay)
        stopcar()
        time.sleep(short_delay)

    if sensorval == "001":
        print("001 slight left")
        forward(mid_speed, high_speed)  # slight left turn
        time.sleep(long_delay)
        stopcar()
        time.sleep(short_delay)

    if sensorval == "110":
        print("110 sharp right")
        turnRight(high_speed, low_speed)  # shart right turn
        time.sleep(long_delay)
        stopcar()
        time.sleep(short_delay)

    if sensorval == "011" or sensorval == "010":
        print(sensorval+" sharp left")
        turnLeft(low_speed, high_speed)  # sharp left turn
        time.sleep(long_delay)
        stopcar()
        time.sleep(short_delay)

    if sensorval == "111" or sensorval == "101":
        print(sensorval+" back to left")
        turnRight(low_speed, high_speed)  # back to left side
        time.sleep(extra_long_delay)
        stopcar()
        time.sleep(short_delay)

    if sensorval == "000":
        print(sensorval+" forward")
        forward(mid_speed, mid_speed)  # go forward
        time.sleep(long_delay)
        stopcar()
        time.sleep(short_delay)


def ticker():
    if cur_status == 'R':
        turnRight(high_speed, 0)
    if cur_status == 'L':
        turnLeft(0, high_speed)
    if cur_status == 'A':
        forward(mid_speed, mid_speed)
    if cur_status == 'B':
        backward(mid_speed, mid_speed)
    if cur_status == 'E':
        stopcar()
    if cur_status == 'T':
        line_tracking()
    if cur_status == 'O':
        obstacle_avoid()


UDP_IP = "192.168.11.5"
UDP_PORT = 8888

sock = socket.socket(socket.AF_INET,  # Internet
                     socket.SOCK_DGRAM)  # UDP
sock.bind((UDP_IP, UDP_PORT))

while True:
    print(cur_status)

    sock.settimeout(0.1)
    try:
        data, addr = sock.recvfrom(1024)  # buffer size is 1024 bytes
    except socket.timeout:
        ticker()
        continue
    if data == b'R':
        cur_status = 'R'

    if data == b'L':
        cur_status = 'L'

    if data == b'A':
        cur_status = 'A'

    if data == b'B':
        cur_status = 'B'

    if data == b'E':
        cur_status = 'E'

    if data == b'T':
        cur_status = 'T'

    if data == b'O':
        cur_status = 'O'



●MCU側
こちらはオリジナルから、ネットワーク情報と送信データを「A」にすることしか変えておりません。
(printfで出力しているものをledの点灯に置き換えておりますが、そこは関係ないかと思っています)

#include "mbed.h"
#include "EthernetInterface.h"
#include "rtos.h"

DigitalOut led1(LED1);
DigitalOut led2(LED2);
DigitalOut led3(LED3);
DigitalOut led4(LED4);

void receive(UDPSocket *receiver);

int main()
{
    // 送信先情報
    const char *destinationIP = "192.168.11.5";
    const uint16_t destinationPort = 8888;
    // 自機情報
    const char *myIP = "192.168.11.4";
    const char *myNetMask = "255.255.255.0";
    const uint16_t receivePort = 5000;
    // 送信データ
    const char sendData[100] = "A";
    led1=1;
    // イーサネット経由でインターネットに接続するクラス
    EthernetInterface net;
    // IPアドレスとPortの組み合わせを格納しておくクラス(構造体でいいのでは?)
    SocketAddress destination, source, myData;
    // UDP通信関係のクラス
    UDPSocket udp;
    // 受信用スレッド
    Thread receiveThread;
    led2=1;
    led1=0;
    /* マイコンのネットワーク設定 */
    // DHCPはオフにする(静的にIPなどを設定するため)
    net.set_dhcp(false);
    // IPなど設定
    net.set_network(myIP, myNetMask, "");
    led2=1;
    led1=1;

    // マイコンをネットワークに接続
    if (net.connect() != 0)
    {
        return -1;
    }
    else
    {
    }

    led3=1;
    led2=0;
    led1=0;

    // UDPソケットをオープン
    udp.open(&net);

    led3=1;
    led2=0;
    led1=1;

    // portをバインドする
    udp.bind(receivePort);

    // 送信先の情報を入力
    destination.set_ip_address(destinationIP);
    destination.set_port(destinationPort);
    // 受信用のスレッドをスタート
    receiveThread.start(callback(receive, &udp));

    while (1)
    {
        if (const int result = udp.sendto(destination, sendData, sizeof(sendData)) < 0)
        {
        led1 = !led1;
        }
        ThisThread::sleep_for(1s);
        led4 = !led4;
    }
    receiveThread.join();

    udp.close();
    net.disconnect();
    return 0;
}

void receive(UDPSocket *receiver)
{
    SocketAddress source;
    char buffer[100];
    while (1)
    {
        memset(buffer, 0, sizeof(buffer));
        if (const int result = receiver->recvfrom(&source, buffer, sizeof(buffer)) < 0)
        {
        led3 = !led3;
        }
        else
        {
        led2 = !led2;
        }
    }
}

0

No Answers yet.

Your answer might help someone💌