Skip to content

Instantly share code, notes, and snippets.

@MaxBareiss
Last active April 26, 2020 15:08
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save MaxBareiss/13bdded08ca45ecbd8709116987a94f4 to your computer and use it in GitHub Desktop.
Save MaxBareiss/13bdded08ca45ecbd8709116987a94f4 to your computer and use it in GitHub Desktop.
Code for Hacksburg's Python Two class
#include <Servo.h>
// The actual location of Servo #1.
int position1 = 0;
// The actual location of Servo #2.
int position2 = 0;
// The target location of Servo #1.
int target1 = 0;
// The target location of Servo #2.
int target2 = 0;
Servo s1;
Servo s2;
void setup()
{
// Start the serial link at 115200 baud.
Serial.begin(115200);
}
void loop()
{
// If we have data...
if (Serial.available()){
// Read the opcode
unsigned char cmd = Serial.read();
switch (cmd){
// If it's a Set command
case 'S':
// Read the target of Servo #1
target1 = Serial.parseInt();
// Read and discard the separator symbol
Serial.read();
// Read the target of Servo #2
target2 = Serial.parseInt();
break;
// If it's an enable command
case 'X':
// Enable Servo #1
s1.attach(5);
// Enable Servo #2
s2.attach(6);
break;
// If it's a disable command
case 'x':
// Disable Servo #1
s1.detach();
// Disable Servo #2
s2.detach();
break;
}
}
// Flush the Serial buffer, removing all contents
while (Serial.available()) Serial.read();
// How far away from our target are we?
int error1 = position1 - target1;
// If we aren't at our target...
if (error1) {
// Move one unit per timestep (10ms) towards our target
position1 = error1 > 0 ? position1-1 : position1+1;
}
// How far away from our target are we?
int error2 = position2 - target2;
if (error2) {
// Move one unit per timestep (10ms) towards our target
position2 = error2 > 0 ? position2-1 : position2+1;
}
// Tell Servo #1 to go to the location we are expecting to be at
s1.write(position1);
// Tell Servo #2 to go to the location we are expecting to be at
s2.write(position2);
// Output Servo #1 position to the host
Serial.print(position1);
// Spacer
Serial.print(";");
// Output Servo #2 position to the host, along with a newline
Serial.println(position2);
// Wait 10ms so that this loop runs at roughly 100Hz.
delay(10);
}
# Use the pyserial library
import serial
# The data in position #1 is an int, the data in position #2 is an int
format = [int, int]
# Open the serial port
# This is machine-specific
with serial.Serial("COM12",115200) as ser:
# Forever
while True:
# 1) Read one line from the serial port
# 2) Convert from bytes to string
# 3) Remove trailing whitespace (the newline character)
# 4) Group based on the spacer character we used on the Arduino
line = ser.readline().decode('ascii').strip().split(';')
# Format each data element based on the format specifier above
line = [func(x) for func,x in zip(format,line)]
# Output to the console
print(line)
# Mostly derived from
# https://github.com/swistakm/pyimgui/blob/master/doc/examples/integrations_pygame.py
# Used for quitting
import sys
# Used for GUI display
import pygame
import OpenGL.GL as gl
# Used for actually rendering the GUI
from imgui.integrations.pygame import PygameRenderer
import imgui
# pyserial library
import serial
# GUI Setup
pygame.init()
size = 800, 600
pygame.display.set_mode(size, pygame.DOUBLEBUF | pygame.OPENGL | pygame.RESIZABLE)
# GUI Rendering Setup
imgui.create_context()
impl = PygameRenderer()
io = imgui.get_io()
io.display_size = size
# Servo Application Setup
# The data in position #1 is an int, the data in position #2 is an int
format = [int, int]
servo1 = 0
servo2 = 0
# Open the serial port
with serial.Serial("COM12",115200) as ser:
# Forever
while True:
# 1) Read one line from the serial port
# 2) Convert from bytes to string
# 3) Remove trailing whitespace (the newline character)
# 4) Group based on the spacer character we used on the Arduino
line = ser.readline().decode('ascii').strip().split(';')
# Format each data element based on the format specifier above
line = [func(x) for func,x in zip(format,line)]
# Process GUI events
for event in pygame.event.get():
if event.type == pygame.QUIT:
sys.exit()
impl.process_event(event)
# Show GUI to user and get data
imgui.new_frame()
imgui.begin("Custom window", True)
imgui.text("Servo1: {}".format(line[0]))
imgui.text("Servo2: {}".format(line[1]))
changed1, servo1 = imgui.slider_int("Servo 1",servo1,0,180,format="%.0f")
changed2, servo2 = imgui.slider_int("Servo 2",servo2,0,180,format="%.0f")
imgui.end()
# If data changed, output to Arduino
if changed1 or changed2:
# Build the command string to be sent to the Arduino
# There is deliberately no trailing newline, the semicolon is
# the separator character. Newlines have different lengths on
# different platforms.
ser.write("S{};{};".format(servo1,servo2).encode('ascii'))
# PyGame Boilerplate
gl.glClearColor(1, 1, 1, 1)
gl.glClear(gl.GL_COLOR_BUFFER_BIT)
imgui.render()
impl.render(imgui.get_draw_data())
pygame.display.flip()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment