Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/64.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 通过串行向arduino发送8位整数_Python_C_Parsing_Arduino_Pyserial - Fatal编程技术网

Python 通过串行向arduino发送8位整数

Python 通过串行向arduino发送8位整数,python,c,parsing,arduino,pyserial,Python,C,Parsing,Arduino,Pyserial,我创建了一个音乐可视化工具,我想使用python的pyserial库通过串行方式将38位整数(0-255)发送到Arduino。我的计算机上有一个名为rgb.txt的文本文件,其中包含以下数据:8255255。我使用以下代码通过串行方式发送数据: import serial, time arduino = serial.Serial('COM3', 9600, timeout=.1) time.sleep(2) #give the connection a second to settle w

我创建了一个音乐可视化工具,我想使用python的
pyserial
库通过串行方式将38位整数(0-255)发送到Arduino。我的计算机上有一个名为
rgb.txt
的文本文件,其中包含以下数据:
8255255
。我使用以下代码通过串行方式发送数据:

import serial, time
arduino = serial.Serial('COM3', 9600, timeout=.1)
time.sleep(2) #give the connection a second to settle

while True:
    with open("rgb.txt") as f:
        rgb = f.read().strip("\n")
    arduino.write(rgb.encode("ASCII"))

    data = arduino.readline()
    if data:
        try:
            print(data.decode('ASCII').strip("\r").strip("\n")) # (better to do .read() in the long run for this reason
        except UnicodeDecodeError:
            pass
    time.sleep(0.1)
#include <stdio.h>
int r = A0;
int g = A1;
int b = A2;
void setup() {
  Serial.begin(9600);
  analogWrite(r, 255); delay(333); analogWrite(r, 0);
  analogWrite(g, 255); delay(333); analogWrite(g, 0);
  analogWrite(b, 255); delay(334); analogWrite(b, 0);
}
void loop() {
  if(Serial.available() > 0) {
    char data = Serial.read();
    char str[2];
    str[0] = data;
    str[1] = '\0';
      Serial.println(str);
    }
  }
我收到它的代码是:

import serial, time
arduino = serial.Serial('COM3', 9600, timeout=.1)
time.sleep(2) #give the connection a second to settle

while True:
    with open("rgb.txt") as f:
        rgb = f.read().strip("\n")
    arduino.write(rgb.encode("ASCII"))

    data = arduino.readline()
    if data:
        try:
            print(data.decode('ASCII').strip("\r").strip("\n")) # (better to do .read() in the long run for this reason
        except UnicodeDecodeError:
            pass
    time.sleep(0.1)
#include <stdio.h>
int r = A0;
int g = A1;
int b = A2;
void setup() {
  Serial.begin(9600);
  analogWrite(r, 255); delay(333); analogWrite(r, 0);
  analogWrite(g, 255); delay(333); analogWrite(g, 0);
  analogWrite(b, 255); delay(334); analogWrite(b, 0);
}
void loop() {
  if(Serial.available() > 0) {
    char data = Serial.read();
    char str[2];
    str[0] = data;
    str[1] = '\0';
      Serial.println(str);
    }
  }
我如何解析它以便接收:

8
255
255

最好是3个不同的变量(
r
g
b
)谢谢

如果始终有一个“,”字符,则可以将其转换为int

uint8_t rgb[3] = {0,0,0};
uint8_t rgbIndex = 0;

void loop() {
  if(Serial.available() > 0) {
    char data = Serial.read();
    if(data < '0' || data > '9')
      rgbIndex++;
    else
      rgb[rgbIndex] = rgb[rgbIndex] * 10 + (data - '0');
  }
}
uint8_t rgb[3]={0,0,0};
uint8_t rgbIndex=0;
void循环(){
如果(Serial.available()>0){
char data=Serial.read();
如果(数据<'0'| |数据>'9')
rgbIndex++;
其他的
rgb[rgbIndex]=rgb[rgbIndex]*10+(数据-'0');
}
}

您现在要做的是读取一个
字符
,将其转换为一个CString
str
,然后在继续下一个
字符
之前将其打印出来

您可能可以按照所需的方式将字节粘在一起,但将接收到的字节读入缓冲区并拆分结果更容易:

从Python中发送RGB值,在末尾用逗号和“\n”分隔,然后在Arduino上执行类似操作(未测试,但您知道):

void循环(){
静态字符缓冲区[12];
静态uint8_t rgb[3];
如果(Serial.available()>0){
Serial.readBytesUntil('\n',缓冲区,12);
int i=0;
char*p=strtok(缓冲区“,”);
while(p){
rgb[i++]=(uint8_t)atoi(p);
p=strtok(空,“,”);
}
//您现在有了rgb[]格式的UINT8
Serial.println(rgb[0]);
Serial.println(rgb[1]);
Serial.println(rgb[2]);
}
}
注意:此代码中没有检查和错误处理

毫无疑问,有更漂亮的方式,但我首先想到了这一点,我认为它会起作用。也可以使用字符串对象来完成,但我尽量不这样做

为了使中的代码正常工作,需要添加一些内容(但我还没有测试这些添加是否足够):

void循环(){
如果(Serial.available()>0){
char data=Serial.read();
如果(数据<'0'| |数据>'9')
rgbIndex++;
其他的
rgb[rgbIndex]=rgb[rgbIndex]*10+(数据-48);
如果(rgbIndex==3){
//您现在有了rgb[]格式的uint_8
Serial.println(rgb[0]);
Serial.println(rgb[1]);
Serial.println(rgb[2]);
rgbIndex=0;
对于(int i=0;iArduino代码:

#include <stdio.h>
int r = A0;
int g = A1;
int b = A2;
void setup() {
  Serial.begin(115200);
  analogWrite(r, 255); delay(333); analogWrite(r, 0);
  analogWrite(g, 255); delay(333); analogWrite(g, 0);
  analogWrite(b, 255); delay(334); analogWrite(b, 0);
}
void loop() {
  static char buffer[12];
  static uint8_t rgb[3];

  if (Serial.available() > 0) {
    Serial.readBytesUntil('\n', buffer, 12);
    int i = 0;
    char *p = strtok(buffer, ",");
    while (p) {
      rgb[i++] = (uint8_t)atoi(p);
      p = strtok(NULL, ",");
    }
    // You now have uint8s in rgb[]
    analogWrite(A0, rgb[0]);
    analogWrite(A1, rgb[1]);
    analogWrite(A2, rgb[2]); 
    Serial.println(rgb[0]);
    Serial.println(rgb[1]);
    Serial.println(rgb[2]);
  }
}

您的原始代码几乎是正确的

您只需要稍微更改格式,以同步到换行符

Python代码
导入序列,时间
arduino=serial.serial('COM3',9600,超时=.1)
时间。睡眠(2)#给连接一秒钟时间来解决
尽管如此:
将open(“rgb.txt”)作为f:
rgb=f.read()
rgb=rgb+'\n'#在rgb值后添加一个换行符,以帮助在Arduino代码中同步。
arduino.write(rgb.encode(“ASCII”))
data=arduino.readline()
如果数据:
尝试:
打印(数据解码('ASCII').strip(“\r”).strip(“\n”))
除UNICEDECODEERROR外:
通过
睡眠时间(0.1)
阿杜伊诺代码 我使用了
sscanf()
从缓冲区读取3个整数,因为它返回了成功扫描到变量中的项目数。我还添加了一些
#defines
,以使其更具可读性和可维护性

#包括
#定义端口_R A0
#定义端口A1
#定义端口_B A2
无效设置()
{
Serial.begin(9600);
模拟写入(端口号255);延迟(333);模拟写入(端口号0);
模拟写入(端口号,255);延迟(333);模拟写入(端口号,0);
模拟写入(端口号B,255);延迟(334);模拟写入(端口号B,0);
}
void循环()
{
uint8_t r,g,b;
if(ReadRGB(r,g,b))
{
模拟写入(端口R,R);
模拟写入(端口G,G);
模拟写入(端口_B,B);
序列号println(r);
序列号println(g);
序列号println(b);
}
}
bool ReadRGB(uint8_t&r、uint8_t&g、uint8_t&b)
{
如果(Serial.available()>0)
{
常量int LENGTH=13;//nnn,nnn,nnn\r\0
字符缓冲区[长度];
size_t count=Serial.readbytesintil('\n',buffer,LENGTH-1);//为空终止符留出空间。
buffer[count]=0;//将空终止符放在读取的最后一个字符之后。
int i=sscanf(缓冲区,“%d,%d”,&r,&g,&b);
返回i==3;//通知我们是否成功读取了3个整数。
}
返回false;
}
关于,它不会在超时时通知。相反,它只返回0,这是一个有效值,因此调用方不知道这是否是由于超时造成的

与存在相同的问题,因为它不会通知调用方返回的字节计数是否是遇到搜索字符或超时的结果。如果由于通信错误而不是预期的
255255
导致的超时而接收到
255255,25
,调用方将不知道。

与C#NET中的健壮方法相比,它返回一个
bool
来指示成功/失败,并通过引用传递解析的
int

更健壮的Arduino代码 要克服串行输入缓冲区为空时在不返回错误代码的情况下超时的
Serial.parseInt()
Serial.readBytesUntil()
问题,可以使用类似这样的方法,即每个
循环读取一个字符()
直到它到达换行符,然后再扫描缓冲区中的3个整数:

#定义端口_ra0
#定义端口A1
#定义端口_B A2
常量int LENGTH=12;//nnn,nnn,nnn\0
字符缓冲区[长度];
无效设置()
{
Serial.begin(9600);
Serial.println(“setup()”);
模拟写入(端口号255);延迟(333);模拟写入(端口号0);
模拟写入(端口号,255);延迟(333);模拟写入(端口号,0);
模拟写入(端口B,255)
255,255,255
a, b, c = 1, 8, 255
import struct

packet = struct.pack('3B',a,b,c)
b'\x01\x08\xff'