通过串行将32位整数从python脚本发送到arduino以用于驱动RGB条

时间:2019-04-13 15:59:31

标签: python arduino

第一篇文章,所以对我轻松一点。

我制作了一个python脚本,该脚本会截取当前显示的屏幕截图,并找到最经常出现的RGB颜色值。

我正在尝试通过串行将其发送到arduino pro micro(带有一些辅助组件)以驱动12v LED灯条。

我将各个红色,绿色和蓝色值进行位移,然后将它们加在一起成为一个无符号的32位整数,以发送到arduino,然后将使用位掩码,然后使用PWM引脚将其恢复为原始值在arduino上控制三个MOSFET(N通道)以驱动RGB条上的各个颜色。每种颜色都有256个值,因此可以用8位表示,如下所示。

32位无符号整数

未使用的蓝绿色红色

00000000 00000000 00000000 00000000

红色面具

00000000 00000000 00000000 11111111

绿色面具

00000000 00000000 11111111 00000000

蓝色面具

00000000 11111111 00000000 00000000

我的问题是python脚本和arduino之间的串行通信似乎无法正常工作,我不知道为什么。与我发送的无符号32位整数的格式有关吗?我并没有真正找到可接受格式的任何信息,并且对串行通信的使用经验很少。

我知道的是arduino电路确实正确连接,因为我可以通过在arduino端指定值来完全驱动RGB条纹。

当连接arduino时,我使用Windows设备管理器中的硬件信息进行连接,因此python脚本肯定已连接至arduino,并且在脚本运行时,我无法使用其他任何东西来连接到arduino arduino。

python脚本正在按我的意图计算和格式化值,因为我可以简单地将它们打印到控制台上,而不用写入串行来确认。


from PIL import Image
import serial
import serial.tools.list_ports
import pyscreenshot as ImageGrab
import time
from collections import Counter

if __name__ == '__main__': ###main program###

    # open comms with arduino
    VID = "2341" #arduino pro micro HEX vendor ID given throught the arduino IDE
    PID = "8037" #arduino pro micro HEX product ID given throught the arduino IDE
    arduino_pro_micro_port = None
    ports = list(serial.tools.list_ports.comports()) #get ports information

    for port in ports:
        if PID and VID in port.hwid: #look for matching PID and VID
            arduino_pro_micro_port = port.device #serial port of arduino nano pro

    if arduino_pro_micro_port == None:
        print("Couldn't find an ardiuno pro micro to communicate with")
    else:
        COMPort = serial.Serial(arduino_pro_micro_port, 115200, writeTimeout = 0) #open connection for RGB values to be written

        while True: #loop forever
            image = ImageGrab.grab() #grab screenshot
            image = image.resize((512, 288)) #20% size for faster processing
            image = image.load() #load image so pixel information can be interrogated

            RGBlist = []

            #seperate pixel tuple into lists for red, green  and blue
            for horizontal in range(0, 512, 1): #for all horizontal pixels
                for vertical in range(0, 288, 1): #for all vertical pixels

                    red = image[horizontal, vertical][0]
                    blue = image[horizontal, vertical][1] << 8
                    green = image[horizontal, vertical][2] << 16
                    RGBlist.append(red + green + blue)

            sendLong = Counter(RGBlist).most_common(1)
            print("send " + str(sendLong[0][0]))
            COMPort.write(sendLong[0][0]) #write RGB to serial port
            print("reci "+ str(COMPort.readline())) #read and print line from arduino
            time.sleep(0.1) #wait 0.1 seconds
```end of python code



```arduino code

//set pin integers for RGB
int LEDRPin = 5;
int LEDGPin = 6;
int LEDBPin = 9;

//setup variable store for RGB values
unsigned long incomingLong = 0; //store the incomoing byte for processing#

unsigned long redMask = 255; //bitmask for red value
unsigned long greenMask = 65280; //bitmask for green value
unsigned long blueMask = 16711680; //bitmask for blue value

unsigned long Rv = 0; //red value will be stored here
unsigned long Gv = 0; //green value will be stored here
unsigned long Bv = 0; //blue value will be stored here

unsigned long SAVE_Rv = 0; //red value will be saved here
unsigned long SAVE_Gv = 0; //green value will be saved here
unsigned long SAVE_Bv = 0; //blue value will be saved here

void setup() {
  //initialise RBG pins as outputs
  pinMode(LEDRPin, OUTPUT);
  pinMode(LEDGPin, OUTPUT);
  pinMode(LEDBPin, OUTPUT);

  //start serial comms
  Serial.begin(115200);
  if(Serial.available())// only send data back if data has been sent
  {
    incomingLong = Serial.read(); //read RGB values from serial port
    Serial.write("Ready");
  }
}

void loop() {
  delay(300);
  if(Serial.available() >= 0) // only send data back if data has been sent
  {
    incomingLong = Serial.read(); //read RGB values from serial port
    Serial.write(incomingLong);

    Rv = redMask & incomingLong; //get red value
    Gv = greenMask & incomingLong; //get green value
    Bv = blueMask & incomingLong; //get blue value

    Rv = Rv >> 0; //shift to LSB
    Gv = Gv >> 8; //shift to LSB
    Bv = Bv >> 16; //shift to LSB

    Rv = (int) Rv; //Cast to int
    Gv = (int) Gv; //Cast to int
    Bv = (int) Bv; //Cast to int

    analogWrite(LEDRPin, Rv); //write red value to output pin
    analogWrite(LEDGPin, Gv); //write green value to output pin
    analogWrite(LEDBPin, Bv); //write blue value to output pin

    SAVE_Rv = Rv;
    SAVE_Gv = Gv;
    SAVE_Bv = Bv;
  }
}

```end of arduino code

1 个答案:

答案 0 :(得分:0)

我已经在python27和arduino Uno上为您的案例编写并测试了我的淡化沟通解决方案,但应该为您提供大致相同的结果。测试它,让我知道您是否需要澄清或卡在某个地方。

# python27

import serial
import serial.tools.list_ports
import struct
import sys

arduino_pro_micro_port = 'COM3'
COMPort = serial.Serial(arduino_pro_micro_port, 115200, writeTimeout = 0)

while True:
    r = 12
    g = 145
    b = 87
    if COMPort.in_waiting:
        #COMPort.write(struct.pack("l", 123)) # sending one long directly
        COMPort.write(struct.pack("BBB", r, g, b)) # B means unsigned byte 
        print COMPort.readline()


// Arduino

void setup() {
  // put your setup code here, to run once:
  //start serial comms
  Serial.begin(115200);
  Serial.println("Ready");
}

void loop() {
  // I'm taking the delay off as that might cause synchronization issues on the receiver side

  while (Serial.available() <= 3); // only send data back if data has been sent
  int r = Serial.read(); //read RGB values from serial port
  int g = Serial.read(); //read RGB values from serial port
  int b = Serial.read(); //read RGB values from serial port
  Serial.println("RGB: ");
  Serial.println(r);
  Serial.println(g);
  Serial.println(b);
  delay(3000);
}