Interface and application programmings

Controlling stepper motor with Python

Given that the stepper motor is my main output device, I tried to write an application to interface a stepper motor to my computer through my board. I used Python to write a small application That send the pulse rate to the microcontroller which will make the motor turn accordingly. A counter is incremented at each iteration and printed on the screen. The microcontroller code is written in Arduino language.

The python codes require installing the serial and wxPython libraries with commandes: pip install PySerial

The board is connected to the PC with an FTDI cable. The port number can be read in the Device Manager in the Control Pannel

photo

Arduino code

const int DIR_1 = 5;
const int STEP_1 = 6;
const int STEP_REV = 200;
int PULSE=1000;

void setup() {
pinMode(STEP_1, OUTPUT);
pinMode(DIR_1, OUTPUT);
digitalWrite(DIR_1, HIGH);
Serial.begin(9600); // opens serial port, sets data rate to 9600 bps
}

void loop() {

if (Serial.available() > 0) {
PULSE = Serial.read(); // read the incoming byte
stepper1_on();
}}

void stepper1_on(void)
{
digitalWrite(STEP_1, HIGH);
delayMicroseconds(PULSE);
digitalWrite(STEP_1, LOW);
delayMicroseconds(PULSE);
}

Python code

import serial
import time
serialInterface = serial.Serial('COM9', 9600)
text = ''
counter = 1

while True:
time.sleep(0.5)
serialInterface.write(100)
counter = counter + 1
text = str(counter)
print("send "+text)

Running first code

Python code with graphic interface

After getting started with a simple Python code I tried to write a more complex code with a graphic interface using the wxPython library. The code take as input a pulse number and sends it to the microcontroller via serial which turns the stepper motor one step according to the value of the pulse. The Arduino code is the same.

The python codes require installing the wxPython library with commandes: pip install -U wxPython

Python code with graphic interface

import serial
import time
import wx

serialInterface = serial.Serial('COM9', 9600)

class MyFrame(wx.Frame):
def __init__(self):
super().__init__(parent=None, title='Pulse input')
panel = wx.Panel(self)
my_sizer = wx.BoxSizer(wx.VERTICAL)
self.text_ctrl = wx.TextCtrl(panel)
my_sizer.Add(self.text_ctrl, 0, wx.ALL | wx.EXPAND, 5)
my_btn = wx.Button(panel, label='Pulse')
my_btn.Bind(wx.EVT_BUTTON, self.on_press)
my_sizer.Add(my_btn, 0, wx.ALL | wx.CENTER, 5)
panel.SetSizer(my_sizer)
self.Show()

def on_press(self, event):
value = self.text_ctrl.GetValue()
pulse_byte=value.encode("utf-8")
serialInterface.write(pulse_byte)


if __name__ == '__main__':
app = wx.App()
frame = MyFrame()
app.MainLoop()

Interface

photo

Running second code

Testing processing with potentiometer input

We tested the Processing language with an input such as a potentiometer. The code plots the variation of the potentiometer. We also tried the same application with Python. Many examples of similar codes are available online, such as in the arduino Library: Arduino tutorial

Arduino code

void setup() {
Serial.begin(9600);
}

void loop() {
// send the value of analog input 0:
Serial.println(analogRead(A0));
delay(2);
}

Processing code

import processing.serial.*;

Serial myPort; // The serial port
int xPos = 1; // horizontal position of the graph
float inByte = 0;

void setup () {

size(400, 300); // set the window size:

println(Serial.list()); // List available serial ports

myPort = new Serial(this, Serial.list()[0], 9600); // Open port in use

myPort.bufferUntil('\n'); // don't generate serialEvent until new character

background(0); // set background:
}

void draw () {

stroke(127, 34, 255); // line style
line(xPos, height, xPos, height - inByte); //line position

if (xPos >= width) {
xPos = 0; // at the edge of the screen, go back to the beginning:
background(0);
} else {
xPos++; // increment the horizontal position:
}
}

void serialEvent (Serial myPort) {

String inString = myPort.readStringUntil('\n'); // get string

if (inString != null) {
inString = trim(inString); // trim off any whitespace:
inByte = float(inString); // convert to an int and map to the screen height
println(inByte);
inByte = map(inByte, 0, 1023, 0, height);
} }

Board

photo

Processing plot

photo

Comparing with Python

I tried the same application with Python. Again many tutorials and Python examples for reading a senor or input are available online.

The python codes require installing the matplotlib library with commandes: python -m pip install -U matplotlib

The python code requires special attention to the format of the characters:

Python code

import serial
import time
import csv
import matplotlib
matplotlib.use("tkAgg")
import matplotlib.pyplot as plt
import numpy as np

ser = serial.Serial('COM9')
ser.flushInput()

plot_window = 20
y_var = np.array(np.zeros([plot_window]))

plt.ion()
fig, ax = plt.subplots()
line, = ax.plot(y_var)

while True:
try:
ser_bytes = ser.readline()
try:
decoded_bytes = float(ser_bytes[0:len(ser_bytes)-2].decode("utf-8"))
print(decoded_bytes)
except:
continue
with open("test_data.csv","a") as f:
writer = csv.writer(f,delimiter=",")
writer.writerow([time.time(),decoded_bytes])
y_var = np.append(y_var,decoded_bytes)
y_var = y_var[1:plot_window+1]
line.set_ydata(y_var)
ax.relim()
ax.autoscale_view()
fig.canvas.draw()
fig.canvas.flush_events()
except:
print("Keyboard Interrupt")
break

Python plot

photo

Testing MIT App inventor with servo

I tested the MIT App inventor with app that controls the rotation angle of a servo motor. The App cosists of List-picker from wich we ca select the Bluetooth connection, and a Slider that sets the rotation angle ranging from 0 to 180 degrees. The value selected by the user on the slider is rounder and sent via Bluetooth to the microcontroller to wich the servo is connected. The graphic layout is defined in the Designer window. The non visible part of the designer section includes a BluetoothClient module (from the connectivity toolbar) and a clock (from the sensor toolbar). The Blocks diagram defines the relation between the different modules. When the timer runs out, if the Bluetooth Client is connected a label signals that the device is connected, then the value of the rotation angle selected with the Slider is sent via Bluetooth. It has to be noted that the pairing between the phone and the HC-06 bluetooth module has to be done on the phone before using the app. The arduino code utilises the SoftwareSerial and the Servo libraries

Arduino code

#include 'SoftwareSerial.h'
#include 'Servo.h'

Servo myservo;

int bluetoothTx=A3;
int bluetoothRx=A2;

SoftwareSerial bluetooth(bluetoothTx,bluetoothRx);

void setup()
{
myservo.attach(9);
Serial.begin(9600);
bluetooth.begin(9600);
}

void loop()
{
if(bluetooth.available()>0)
{
int toSend = bluetooth.read();
Serial.println(toSend);
myservo.write(toSend);
}
}


Testing app

Designer window

photo

Blocks window

photo