Week assignments

Individual assignment:

  • Write an application that interfaces with an input and/or output device that you made.

Group assignment:

  • Compare as many tool options as possible

Group assignment

You can find documentation about our group assignement on our group page.

Tkinter hello.switch test

The first thing I wanted to do this weekend was to use my input device board to interface a pressbutton pressed or not.
It is convenient since it already has button and a FTDI header.
I had never used Tkinter but I am confortable enough with Python and since there is many example wrote by Neil, I though it would be easier to go this way to complete the week assignement.
So I copied Neil's hello code for motion detection and modified for my purpose.

from tkinter import *
import serial

WINDOW = 200  # window size
port = "COM6" # I know what port is my board connected to.


def idle(parent, canvas):
    char = ser.read()
    if (char == b'1'): # Pressing the switch on my board makes it send 1's.
        canvas.itemconfigure("rect", fill="#b00000")
        canvas.itemconfigure("text", text="pressed")
    else:
        canvas.itemconfigure("rect", fill="#0000b0")
        canvas.itemconfigure("text", text="not pressed")
    canvas.update()
    parent.after_idle(idle, parent, canvas)


ser = serial.Serial(port, 9600)
ser.setDTR()
ser.flush()

root = Tk()
root.title('hello.switch')
root.bind('q', 'exit')
canvas = Canvas(root, width=2 * WINDOW, height=3 * WINDOW, background='white')
canvas.create_text(.5 * WINDOW, .5 * WINDOW, text="read", font=("Helvetica", 24), tags="text", fill="#0000b0")
canvas.create_rectangle(WINDOW, 0, 2 * WINDOW, WINDOW, tags='rect', fill='#b00000')
canvas.pack()

root.after(100, idle, root, canvas)
root.mainloop()

I uploaded the code below to my board to detect and send 1's when the switch button is pressed:

#include <SoftwareSerial.h>
#define RX    7   // *** D3, Pin 2
#define TX    6   // *** D4, Pin 3

SoftwareSerial MySerial(RX, TX);

const int l1 = 1;
const int c1 = 3;

void setup() {
  pinMode(l1, INPUT_PULLUP); //Therefore L1 is normally HIGH
  pinMode(c1, OUTPUT);
  MySerial.begin(9600);
}

void loop() {
  digitalWrite(c1, LOW);   // turn the LED on (HIGH is the voltage level)
  if (digitalRead(l1)==LOW) {
    MySerial.print(1);
    delay(10);
  }
  else {
    MySerial.print(0);
    delay(10);
  }
}

At first I was just sending 1's when the button was pressed and nothing when it was released. But the ser.read() python command wait for something to be written and my Tkinter interface could'nt print that the button was released.
By sending 0's everything went alright.

Matrix detection interface

My second objective for the week was to build an interface to represent the matrix detection of my chess pieces. The picture below show the vynilcutted copper tape matrix with or without the 2mm thick medium panel on top of it.

4x4 Copper Tape Matrix

For the arduino I used the code below.

int i_min = 0;
int i_max = 4;
int j_min = 0;
int j_max = 4;
int nloop = 100;
int count, i, j;
int up[4][4],down[4][4],value[4][4];
int x;
double eps = 0.1;
double filt[4][4];
String str_filt ="";

void setup() {
  for (i = i_min; i<i_max; i++){
    for (j = j_min; j<j_max; j++){
      filt[i][j] = 0.000;
    }
  }
  pinMode(A0, INPUT);
  pinMode(A1, INPUT);
  pinMode(A2, INPUT);
  pinMode(A5, INPUT);
  pinMode(10, OUTPUT);
  pinMode(11, OUTPUT);
  pinMode(12, OUTPUT);
  pinMode(13, OUTPUT);
  Serial.begin(9600);
}

void loop() {
  //This part is for capacitive sensing
  for (i = i_min; i<i_max; i++){
    for (j = j_min; j<j_max; j++){
      up[i][j] = 0;
      down[i][j] = 0;
      for (count = 0; count < nloop; ++count){
        delayMicroseconds(0.1);
        digitalWrite(j+10, HIGH);
        x = analogRead(i);
        up[i][j] += x;
        delayMicroseconds(0.1);
        digitalWrite(j+10, LOW);
        x = analogRead(i);
        down[i][j] += x;
        }
      value[i][j] = up[i][j] - down[i][j];
      filt[i][j] = (1-eps)*filt[i][j] + eps*value[i][j];
    }
  }
  //This part is for communication with my Python programm
  str_filt="";
  for (j = j_min; j<j_max; j++){
    for (i = i_min; i<i_max; i++){
      str_filt = str_filt + "," + String(filt[i][j]);
    }
  }
  Serial.println(str_filt + ",");
}

For the Python code I used the code below

from tkinter import *
import serial
import time

WINDOW = 280
port = "COM21"

def idle(parent, canvas):
    data = ser.readline()[:-2]
    my_list = str(data).split(",")
    del my_list[0]
    del my_list[-1]
    for i in range(len(my_list)):
        try:
            my_list[i] = float(my_list[i])
        except:
            my_list[i] = 0
    # print(my_list)
    # print(trigger)
    for i in range(len(my_list)):
    #if the capacitive sensor is higher than trigger, then a whasher is detected, turn the blue square to red.
        if (my_list[i] > trigger[i]):
            canvas.itemconfigure(i + 1, fill="#b00000")
        else:
            canvas.itemconfigure(i + 1, fill="#0000b0")
    canvas.update()
    parent.after_idle(idle, parent, canvas)


ser = serial.Serial(port, 9600)
ser.setDTR()
ser.flush()

for j in range(60):
    data = ser.readline()[:-2]
my_list = str(data).split(",")
del my_list[0]
del my_list[-1]
trigger = [0 for i in range(len(my_list))]
for i in range(len(my_list)):
    try:
        my_list[i] = float(my_list[i])
    except:
        my_list[i] = 0
print(my_list)
for i in range(len(my_list)):
    trigger[i] = my_list[i] + 100.00
    # I declare the value at which an object is detected: a hundred more than where there is nothing.

root = Tk()
root.title('hello.capacitive.matrix')
root.bind('q', 'exit')
canvas = Canvas(root, width=3.5 * WINDOW, height=3.5 * WINDOW, background='white')
for i in range(0, 4) :
    for j in range(0, 4) :
        canvas.create_rectangle(j * WINDOW, (3.5 - i) * WINDOW, (j + 0.5) * WINDOW, (3 - i) * WINDOW, tags=j + 1 + 4 * i, fill='#0000b0')
canvas.pack()
root.after(100, idle, root, canvas)
root.mainloop()

The video below show the result of the detection.

I used the canvas tool in Tkinter to create the 4*4 matrix of squares.
The loop below allowed me to do them with equal spacing and to fill them in blue by default. I also gave a tag to every of them to know there position.

for i in range(0, 4) :
    for j in range(0, 4) :
        canvas.create_rectangle(j * WINDOW, (3.5 - i) * WINDOW, (j + 0.5) * WINDOW, (3 - i) * WINDOW, tags=j + 1 + 4 * i, fill='#0000b0')

Then, on every loop, my computer read the data sent by the capacitive sensing board and compare it the trigger value at which it knows if there is a washer or not. If there is one, it turns the square to red otherwise, it turn it blue. This is done with the code below.

for i in range(len(my_list)):
  if (my_list[i] > trigger[i]):
      canvas.itemconfigure(i + 1, fill="#b00000")
  else:
      canvas.itemconfigure(i + 1, fill="#0000b0")

What can be improved

  • having the detection faster:
    • play with epsilon value
    • better understanding of capacitive sensing theory
  • avoid interference between each square:
    • sometime two squares appear to be detected because of only one washer this could be better managed with more signal processing
  • transfer code from C to python:
    • I transform floats to strings and then back to a list of float