简体   繁体   中英

python + arduino controlling DC Motor

Hi This is my Arduino code, since I want the loop only once, I used the while(1) {} construct in the void loop()

int motorPin = 3;
int motorDir = 12;
int motorBr = 9;

void setup() {
 //pinMode(motorPin, OUTPUT);
 pinMode(motorBr, OUTPUT);  
 pinMode(motorDir, OUTPUT);

 if (Serial.available() > 0) {

  if(Serial.read() == '1') {    
    digitalWrite(motorBr, LOW);
    digitalWrite(motorDir, HIGH);
    digitalWrite(motorPin, HIGH);
    delay(500); 
    digitalWrite(motorBr, HIGH);


  } else if(Serial.read() == '0') {
    digitalWrite(motorBr, LOW);
    digitalWrite(motorDir, LOW);
    digitalWrite(motorPin, HIGH);
    delay(500); 
    digitalWrite(motorBr, HIGH);
  }
 }

}

void loop() { while(1) {}
  }

This is my python code

import serial
import time

ser = serial.Serial('COM3', 9600, timeout=1)
time.sleep(2)



#I am forcing the script to write 1 to Arduino to make the motor turn

ser.write(b'1')

ser.flush()

time.sleep(2)

ser.close()

The communication isn't happening. Any insight should help. I am using Python 3.5 and Arduino Uno with the updated drivers.

Edit:

Hi Julien, yes the following code does its job:

int motorPin = 3;
int motorDir = 12;
int motorBr = 9;

void setup() {
 // put your setup code here, to run once:
 //pinMode(motorPin, OUTPUT);
 pinMode(motorBr, OUTPUT);  
 pinMode(motorDir, OUTPUT);

 digitalWrite(motorBr, LOW);
 digitalWrite(motorDir, HIGH);
 digitalWrite(motorPin, HIGH);
 delay(500); 
 digitalWrite(motorBr, HIGH);

 delay(2000);

 digitalWrite(motorBr, LOW);
 digitalWrite(motorDir, LOW);
 digitalWrite(motorPin, HIGH);
 delay(500); 
 digitalWrite(motorBr, HIGH);
}

void loop() {
  // put your main code here, to run repeatedly:
}

I have also made the following changes

ser.write('1') --> ser.write(b'1')

Serial.read() == 1 --> Serial.read() == '1' 

Serial.read() == 1 --> Serial.read() == 0x31 

doesn't seem to have any effect.

The way I am accomplishing this is first uploading the Arduino program to memory, then running the Python script. No errors show up either..

Execution of the Ardiono code via Subprocess call in Python:

import subprocess

actionLine = "upload"
projectFile = "C:/Users/Tomography/Desktop/DCM2/DCM2.ino"
portname = "COM3"
boardname = "arduino:avr:uno"

#I added the ardiono.exe to path, the command automatically sources the 
Command = "arduino" + " --" + actionLine +" --board " + boardname + " --port " + portname + " " + projectFile

print(Command)

result = subprocess.call(Command)

if result != 0:
 print("\n Failed - result code = %s --" %(result))
else:
 print("\n-- Success --")

Old post but I figured I'd post my findings with this incase anybody else sees this in the future.

In the arduino file under the void setup() make sure to include

Serial.begin(9600);

Otherwise the connection won't be established.

Here is the completed working code I used to turn the motor on and off using 1 or 0 in python:

Arduino Code:


void setup() {
  pinMode(motorPin, OUTPUT);
  Serial.begin(9600);
}

void loop() //This will be executed over and over
{ 
    if (Serial.available() > 0) {
        if(Serial.read() == '1') {
          analogWrite(motorPin, 50);
        } 
        else if(Serial.read() == '0') {
          analogWrite(motorPin, 0);
        }
    }
}

Python Code:

import serial
import time

ser = serial.Serial('COM3', 9600) //established connection

time.sleep(2)

ser.write(b'1') ##sends '1' to serial 

time.sleep(5) ##motor runs for this period

ser.write(b'0') ##sends '0' to serial on arduino to turn motor off

ser.close()

try this :

import serial
import time

ser = serial.Serial('COM3', 9600, timeout=1) #here you may add write_timeout=1 to avoid indefinite blocking on failing flush

time.sleep(2)

ser.write('1')
ser.flush() #force the physical write

#time.sleep(2) #no need to sleep as flush was blocking

ser.close()

for the Arduino code, the test on Communication happens only once as it is located in setup function. The loop() is the equivalent of the while(1) in the main loop that you may know from "normal" C codes.

Reference manual for setup

Reference manual for loop

This means your arduino code is already in the while(1) in loop() once you execute the Python and it will never be alowed to analyse the serial data.

The correct Arduino code would be :

int motorPin = 3;
int motorDir = 12;
int motorBr = 9;

void setup() //this is executed only once at init
{
 //pinMode(motorPin, OUTPUT);
 pinMode(motorBr, OUTPUT);  
 pinMode(motorDir, OUTPUT);
}

void loop() //This will be executed over and over
{ 
    if (Serial.available() > 0) {

        // here '1' (the character) is important as 1 is the number
        // and '1' equals 0x31 (ASCII)
        if(Serial.read() == '1') {   
            digitalWrite(motorBr, LOW);
            digitalWrite(motorDir, HIGH);
            digitalWrite(motorPin, HIGH);
            delay(500); 
            digitalWrite(motorBr, HIGH);
        } else if(Serial.read() == '0') {
            digitalWrite(motorBr, LOW);
            digitalWrite(motorDir, LOW);
            digitalWrite(motorPin, HIGH);
            delay(500); 
            digitalWrite(motorBr, HIGH);
        }
    }
}

Your Python code is sending the string '1', but your arduino code is looking for the number 1. Try changing the arduino code to this

Serial.read() == 0x31

and

Serial.read() == 0x30

Those are the ASCII codes for the '1' and '0' respectively

The code in your setup() function has most likely already ran by the time you send the character from your python script.

Place the code in the loop() function and then place some logic in the loop function so it only runs once.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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