ADVERTISEMENT
Arduino ultrasonic computer interface- as there are only two sensors the active area is small |
The whole set up in action can be seen in the video below. Basically the limitation in the active pointer area is small due to the limited number of sensors used. But this can be used as a base and adding more sensors can improve the results. Currently i used it to plot on a gui based on python (matplotlib) and can be extended as a real mouse by adding a few more lines of code and the V-USB on arduino uno or using a leonardo/ newer version of micro-controllers which can act as a usb HID.
The arduino sketch is very simple and it basically sends x and y cordinates via serial to the computer and on the PC , just plot the x,y values on a 2d plane
Code
sonic_mouse.ino
// a simple sonic mouse, code adapted from New ping example
// Connect PIN 13 to Trigger of first sensor and 12 to the Echo pin
// Connect PIN 11 to Trigger of second sensor and 10 to the Echo pin
// If you use multiple sensor for x / y axis, use the max value from the read array along the axis
// Read more about it at http://blog.riyas.org
#include <NewPing.h>
#define SONAR_NUM 2 // Number or sensors.
#define MAX_DISTANCE 50 // Maximum distance (in cm) to ping.
#define PING_INTERVAL 33 // Milliseconds between sensor pings (29ms is about the min to avoid cross-sensor echo).
unsigned long pingTimer[SONAR_NUM]; // Holds the times when the next ping should happen for each sensor.
unsigned int cm[SONAR_NUM]; // Where the ping distances are stored.
uint8_t currentSensor = 0; // Keeps track of which sensor is active.
NewPing sonar[SONAR_NUM] = { // Sensor object array.
NewPing(13, 12, MAX_DISTANCE), // Each sensor's trigger pin, echo pin, and max distance to ping.
NewPing(11, 10, MAX_DISTANCE),
};
void setup() {
Serial.begin(115200);
pingTimer[0] = millis() + 75; // First ping starts at 75ms, gives time for the Arduino to chill before starting.
for (uint8_t i = 1; i < SONAR_NUM; i++) // Set the starting time for each sensor.
pingTimer[i] = pingTimer[i - 1] + PING_INTERVAL;
}
void loop() {
for (uint8_t i = 0; i < SONAR_NUM; i++) {
if (millis() >= pingTimer[i]) {
pingTimer[i] += PING_INTERVAL * SONAR_NUM;
if (i == 0 && currentSensor == SONAR_NUM - 1) SensorReadLoop();
sonar[currentSensor].timer_stop();
currentSensor = i;
cm[currentSensor] = 0;
sonar[currentSensor].ping_timer(echoCheck);
}
}
// eXTRA CONTROL CAN BE DONE HERE
}
void echoCheck() {
if (sonar[currentSensor].check_timer())
cm[currentSensor] = sonar[currentSensor].ping_result;
}
void SensorReadLoop() { // ADDITIONALLY HERE you CAN ADD THE v-usb
for (uint8_t i = 0; i < SONAR_NUM; i++) {
Serial.print(cm[i]);
Serial.print(" ");
}
Serial.print("\n");
}
Plotting the pointer data from arduino on the computer using python and matplotlib
Copy the following code in to a new file plot_mouse.py and execute it by typing python plot_mouse.py in a terminal. On windows, you need to modify it (first make sure to get the python serial and matplotlib working )################################################################################
# plot_mouse.py
# Plot the data from sonic_mouse.ino on a pc
# It uses matplotlib
# install matplotlib, pyserial and numpy to get it working
# code adapted from https://gist.github.com/electronut/5641938
# more details on the project at http://blog.riyas.org
################################################################################
import sys, serial
import numpy as np
from time import sleep
from collections import deque
from matplotlib import pyplot as plt
# store the pointer data
class PointerData:
def __init__(self, maxLen):
self.ax = deque([0.0]*maxLen)
self.ay = deque([0.0]*maxLen)
self.maxLen = maxLen
def addToBuf(self, buf, val):
if len(buf) < self.maxLen:
buf.append(val)
else:
buf.pop()
buf.appendleft(val)
def add(self, data):
assert(len(data) == 2)
self.addToBuf(self.ax, data[0])
self.addToBuf(self.ay, data[1])
class PlotData:
def __init__(self, PointerData):
plt.ion()
self.axline, = plt.plot(PointerData.ax,PointerData.ay,'r',linewidth=10)
mng = plt.get_current_fig_manager()
mng.resize(*mng.window.maxsize())
plt.ylim([0, 2000])
plt.xlim([0, 2000])
def update(self, PointerData):
self.axline.set_xdata(PointerData.ax)
self.axline.set_ydata(PointerData.ay)
plt.draw()
# main() function
def main():
if(len(sys.argv) != 2):
print 'Example usage: python plot_mouse.py "/dev/ttyACM0"'
exit(1)
strPort = sys.argv[1];
PointerData = PointerData(4)
PlotData = PlotData(PointerData)
# open serial port
ser = serial.Serial(strPort, 115200)
while True:
try:
line = ser.readline()
#print line
data = [float(val) for val in line.split()]
if(len(data) == 2):
PointerData.add(data)
PlotData.update(PointerData)
except KeyboardInterrupt:
print 'exiting'
break
ser.flush()
ser.close()
# call main
if __name__ == '__main__':
main()
end
No comments:
Post a Comment