From 91d6b5af4b7cecba8b73f345b4f8b3a8a56f37b9 Mon Sep 17 00:00:00 2001 From: Phyks Date: Mon, 30 Sep 2013 23:05:02 +0200 Subject: [PATCH] Handle 3 electrodes The code should be able to handle 3 electrodes for R, G and B. Didn't test it so far (need 2 other electrodes). --- color.py | 60 +++++++++++------ touchless_tracking/touchless_tracking.ino | 78 +++++++++++++++++------ 2 files changed, 101 insertions(+), 37 deletions(-) diff --git a/color.py b/color.py index 932cf81..1a0b6d5 100755 --- a/color.py +++ b/color.py @@ -3,49 +3,71 @@ import serial import pygame + +def compute_value(line, minimum, maximum): + line = line.split(" ") + if len(line) < 3: + return False + + for i in range(3): + value[i] = int(255*(line[i]-minimum[i])/(maximum[i]-minimum[i])) + if value[i] > 255: + value[i] = 255 + elif value[i] < 0: + value[i] = 0 + + return value[0], value[1], value[2] + + ser = serial.Serial("/dev/ttyACM0", 115200) pygame.init() size = width, height = 640, 480 screen = pygame.display.set_mode(size) +pygame.display.set_caption("Touchless 3D tracking") screen.fill((0, 0, 0)) try: ser.open() -except Exception: - print("Error while opening serial port.") +except Exception as e: + print("Error while opening serial port : "+str(e)) if ser.isOpen(): try: ser.flushInput() ser.flushOutput() - maximum = -1 - minimum = -1 + maximum = [-1, -1, -1] + minimum = [-1, -1, -1] print("Calibration :") pygame.display.flip() - for i in range(50) : + for i in range(50): line = float(ser.readline()) if line < minimum or minimum < 0: - minimum = line - if line > maximum: - maximum = line + minimumR = line + if line > maximum: + maximumR = line print("Go :") - while True: - line = float(ser.readline()) - valueR = int(255*(line-minimum)/(maximum-minimum)) - if valueR < 0: - valueR = 0 - if valueR > 255: - valueR = 255 + running = True + while running: + # Quit if window is closed + for event in pygame.event.get(): + if event.type == pygame.QUIT: + running = False - screen.fill((valueR, 0, 0)) - pygame.display.flip() + # Read line from serial + line = float(ser.readline()) + # Compute the value for red + value = compute_value(line, minimum, maximum) + + if value is not False: + screen.fill(value) + pygame.display.flip() ser.close() - except Exception: - print("Error while fetching data from serial.") + except Exception as e: + print("Error while fetching data from serial : "+str(e)) diff --git a/touchless_tracking/touchless_tracking.ino b/touchless_tracking/touchless_tracking.ino index b3e08bc..b209671 100644 --- a/touchless_tracking/touchless_tracking.ino +++ b/touchless_tracking/touchless_tracking.ino @@ -1,16 +1,47 @@ -#define resolution 8 -#define mains 50 // 60: north america, japan; 50: most other places +/* Touchless tracking + * ================== + * This code takes as many measurements as it can at approximately + * 10Hz = 60 Hz / (2 full cycles * 3 sensors). + * + * The code takes as many measurements as possible on the period of two + * cycles of the main power frequency, in order to cancel out any potential + * coupling. + * + * Original code was found on instructables : + * http://www.instructables.com/id/DIY-3D-Controller/ + * + * Code slightly modified and commented by Phyks for HackENS + * + * As I found the code on Instructables and I don't give a damn to the + * modifications I made, you may reuse it freely by writing where you + * found it. + */ +#define resolution 8 +// Frequency of main power to avoid coupling +#define mains 50 +// Time between measures #define refresh 2 * 1000000 / mains +// Pins to use +// Must be between 8 and 13 to use this code without +// modifications (PORTB is for pins 8 to 13) +// +// Note : If you change pin numbers, you *must* change the mask. +// See arduino doc for more info. +#define PIN_R 8 +#define MASK_R B00000001 +#define PIN_G 9 +#define MASK_G B00000010 +#define PIN_B 10 +#define MASK_B B00000100 + // Counter for the timer extern volatile unsigned long timer0_overflow_count; -/* === */ -/* ??? */ void startTimer() { timer0_overflow_count = 0; - TCNT0 = 0; + TCNT0 = 0; // Initialize counter value to 0 } unsigned long checkTimer() { @@ -19,40 +50,51 @@ unsigned long checkTimer() { long time(int pin, byte mask) { unsigned long count = 0, total = 0; - + while(checkTimer() < refresh) { - // pinMode is about 6 times slower than assigning + // Note : pinMode is about 6 times slower than assigning // DDRB directly, but that pause is important + + // Set pin as output and LOW, see arduino doc for info on PORTB pinMode(pin, OUTPUT); PORTB = 0; - + + // Set it as INPUT to take measure pinMode(pin, INPUT); - + + // While PINB is low, increment counter while((PINB & mask) == 0) count++; - + total++; } + // Restart timer for next measurement startTimer(); + // Return the measurement result return (count << resolution) / total; } -/* ??? */ -/* === */ - void setup() { // Initialize serial communication Serial.begin(115200); - - // INPUT on pin 8 - pinMode(8, INPUT); - + + // INPUT on pins + pinMode(PIN_R, INPUT); + pinMode(PIN_G, INPUT); + pinMode(PIN_B, INPUT); + // Start timer startTimer(); } void loop() { // Print output to serial in decimal - Serial.print(time(8, B00000001), DEC); + Serial.print(time(PIN_R, MASK_R), DEC); Serial.print(" "); + + Serial.print(time(PIN_G, MASK_G), DEC); + Serial.print(" "); + + Serial.print(time(PIN_B, MASK_B), DEC); + Serial.print("\n"); }