ソースを参照

Arduino protocol specified.

Fred Damstra 7 年 前
コミット
3a9ff5c486
3 ファイル変更169 行追加7 行削除
  1. 139 1
      README.md
  2. 2 2
      facetracker.py
  3. 28 4
      i2c_console.py

+ 139 - 1
README.md

@@ -1,4 +1,142 @@
-Be sure to calibrate your lens using the fisheye correction instructions here:
+# OCT - The Oreo Cookie Thrower
+
+A face tracking, cookie throwing robot. Uses an arduino and a raspberry together. Almost 100% 3D printed.
+
+Disclaimer: I do not know what I'm doing. What you see below is stuff that worked through some
+research (probably not enough) along with some trial and error. I'm sure there are a lot of 
+improvements that could be made and probably some straight out mistakes.
+
+## Hardware
+* 3D Printed OCT Parts
+* Plenty of M3 nuts and bolts of varying lengths
+* An appropriately sized spring
+* Small stepper motors with drivers. I used cheap [12V 28byj-48 motors with ULN2003 drivers](https://www.aliexpress.com/item/12V-28BYJ-48-Stepper-Motor-ULN2003-Stepper-Motor-Drive-Test-Module-Board/2055102941.html)
+* 1k resistors
+* Capacitors
+* Diodes
+* 12V DC adapter
+* Something to drop voltage down to 5V DC for the pi
+* magetic switch
+* endstops (maybe?)
+* A momentary push button
+* A power button
+
+## Tools
+* Hex Drivers
+* Screwdrivers
+* Drill
+
+## Circuit Elements
+
+Summary:
+| Device 1     | Pin             | Device 2     | Pin          | Purpose      |
+|--------------|-----------------|--------------|--------------|--------------|
+| Uno          | A0              | Motor 1      | 1 (1kohm)    | Motor Driver |
+| Uno          | A1              | Motor 1      | 2 (1kohm)    | Motor Driver |
+| Uno          | A2              | Motor 1      | 3 (1kohm)    | Motor Driver |
+| Uno          | A3              | Motor 1      | 4 (1kohm)    | Motor Driver |
+| Uno          | 5               | Reed Switch  | 1            | Load Detect  |
+| Uno          | 6               | Motor 2      | 1 (1kohm)    | Motor Driver |
+| Uno          | 7               | Motor 2      | 2 (1kohm)    | Motor Driver |
+| Uno          | 8               | Motor 2      | 3 (1kohm)    | Motor Driver |
+| Uno          | 9               | Motor 2      | 4 (1kohm)    | Motor Driver |
+| Uno          | 10              | Motor 3      | 1 (1kohm)    | Motor Driver |
+| Uno          | 11              | Motor 3      | 2 (1kohm)    | Motor Driver |
+| Uno          | 12              | Motor 3      | 3 (1kohm)    | Motor Driver |
+| Uno          | 13              | Motor 3      | 4 (1kohm)    | Motor Driver |
+| Pi           | SDA (Pin 3)     | Uno          | A4           | i2c          |
+| Pi           | SCL (Pin 5)     | Uno          | A5           | i2c          |
+| Pi           | GPIO26 (Pin 37) | Momentary B1 | 1            | Mode Select  |
+| Pi           | GPIO20 (Pin 38) | Momentary B2 | 1            | Fire         |
+
+TODO: Output of some sort to determine current mode. LEDs? LCD Display? Speaker?
+
+### i2c connection
+The Raspberry Pi is connected to the raspberry pi via i2c. According to [Oscar Liang](https://oscarliang.com/raspberry-pi-arduino-connected-i2c/),
+this works just fine despite the differing logic levels, provided the Pi is the master.
+
+There is no need for any additional hardware nor resistors.
+
+#### i2c Uno Configuration
+Pi Pin 3 (SDA) <-> Arduino Uno Pin A4 (SDA)
+Pi Pin 5 (SCL) <-> Arduino Uno Pin A5 (SCL)
+
+#### i2c MEGA Configuration
+Pi Pin 3 (SDA) <-> Arduino MEGA Pin 20
+Pi Pin 5 (SCL) <-> Arduino MEGA Pin 21
+
+### Motor Connections
+For my design, I used the ULN2003 drivers. I believe these are supposed to be test boards, but they work well enough. I put a good
+sized capacitor (70uF?) across the positive/negative leads in case of sudden current draw, and also placed a diode running from the
+negative lead to the positive lead as an extra suppression diode. The ULN2003 has built in suppression diodes, but after losing
+my serial interface on my arduino, I decided it best to add some extra protection. For that matter, I also added diodes before the 
+Vin of the Arduino.
+
+To protect the output pins from backcurrent, install a 1kohm resister inline with each of the 12 pins below.
+
+#### Arduino Uno Motor Connections
+Order of "Motor 1" through Motor 3" depends on your wiring. It doesn't matter provided it matches the code. For that matter,
+the actual pins don't matter, either. Use whatever's easiest to wire.
+
+Arduino Uno Pin A0, A1, A2, A3 -> 1kohm resistor -> Motor 1
+Arduino Uno Pin 6, 7, 8, 9 -> 1kohm resistor -> Motor 2
+Arduino Uno Pin 10, 11, 12, 13 -> 1kohm resitor -> Motor 3
+
+### Switches
+#### Magnetic (Reed) Switch
+A reed switch is used to determine when the arm has reached the reload position. Place the magnet on the launch arm, and 
+the reed switch on the base. This uses the arduinos internal pullup resistor for logic.
+
+Reed switch wire 1 -> GND
+Reed switch wire 2 -> Arduino Uno Pin 5
+
+#### Endstops
+It would probably be wise to use endstops to prevent the vertical motor from traveling too far. I haven't done that, but
+don't see any reason why it couldn't be done.
+
+#### Mode Select Button
+A mode select button should be wired to the raspberry pi gpio 26 (Pin 37, opposite the SDA pin).  Uses the raspberry
+pi's built-in pullup resistor, so the second pin should be attached go ground.
+
+Mode Select Pin 1 -> GND
+Mode Select Pin 2 -> Pi GPIO 26 (Pin 37)
+
+#### Fire Button
+A fire button should be wired to the raspberry pi gpio 20 (Pin 38.  Uses the raspberry
+pi's built-in pullup resistor, so the second pin should be attached go ground.
+
+Fire Select Pin 1 -> GND
+Fire Select Pin 2 -> Pi GPIO 20 (Pin 38)
+
+
+
+## Code Elements
+
+### Fisheye Camera
+If using a fisheye camera, be sure to calibrate your lens using the fisheye correction instructions here
+and enter them in the code.
 https://medium.com/@kennethjiang/calibrate-fisheye-lens-using-opencv-333b05afa0b0
 
+### i2c Communication
+
+# Messages from Pi to Arduino
+
+| Character | Function                        |
+|+---------+|---------------------------------|
+| w         | Aim higher
+| s         | Aim lower
+| a         | Aim left
+| d         | Aim right
+| r         | Increase load arm (see note 1)
+| f         | reverse load arm (no effect)
+| space     | Stop all
+| L         | Move until load switch activates
+| F         | Fire and reload (see note 2)
+
+note 1: Arduino will stop automatically when the
+load sensor comes on.
+
+note 2: For "Fire", if the load switch is not activated, it will perform a load 
+action first, and then move forward until the switch deactivates, and
+then load again. The end result is that it is reloaded.
 

+ 2 - 2
facetracker.py

@@ -160,7 +160,7 @@ for frame in camera.capture_continuous(rawCapture, format="bgr", use_video_port=
             cv2.circle(image, (int(x+w/2), int(y+h/2)), int((w+h)/3), (255, 255, 255), 1)
 
         # Temporary, save the image
-        cv2.imwrite("tmp/img.{}.png".format(datetime.now().strftime("%Y%m%d.%H%M%S.%f")), image)
+        cv2.imwrite("tmp/img.{}.facetype{}.png".format(datetime.now().strftime("%Y%m%d.%H%M%S.%f"), lastface), image)
 
         # Find the centermost face
         curdistance = 1000000 # Outside the dimensions of the picture
@@ -180,7 +180,7 @@ for frame in camera.capture_continuous(rawCapture, format="bgr", use_video_port=
     lastTime = time.time()*1000.0
        
     # Determine directions and distance
-    travel = [(cameracenter[0] - target[0])/camera.resolution[0], cameracenter[1] - target[1]/camera.resolution[1]]
+    travel = [ (cameracenter[0] - target[0]) / camera.resolution[0], (cameracenter[1] - target[1]) /camera.resolution[1] ]
     print("To move horizontal: {}, vertical: {}".format(travel[0], travel[1]))
     
 

+ 28 - 4
i2c_console.py

@@ -1,5 +1,26 @@
 #! /usr/bin/python3
-
+#
+# For etsting the Pi to Arduino i2c communication and
+# process.
+#
+#| Character | Function                        |
+#|+---------+|---------------------------------|
+#| w         | Aim higher
+#| s         | Aim lower
+#| a         | Aim left
+#| d         | Aim right
+#| r         | Increase load arm (see note 1)
+#| f         | reverse load arm (no effect)
+#| space     | Stop all
+#| L         | Move until load switch activates
+#| F         | Fire and reload (see note 2)
+#
+#note 1: Arduino will stop automatically when the
+#load sensor comes on.
+#
+#note 2: For "Fire", if the load switch is not activated, it will perform a load 
+#action first, and then move forward until the switch deactivates, and
+#then load again. The end result is that it is reloaded.
 import smbus
 import time
 
@@ -17,11 +38,14 @@ SLAVE_ADDRESS = 0x04
 #    return number
 
 while True:
-    var = input("Enter asdwrf :")
+    var = input("Enter asdwrf, <space>, L, or F :")
     if not var:
         continue
 
-    bus.write_byte(SLAVE_ADDRESS, ord(var[0]))
-    print("Sent '{}' to pi.".format(ord(var[0])))
+    try:
+        bus.write_byte(SLAVE_ADDRESS, ord(var[0]))
+        print("Sent '{}' to pi.".format(ord(var[0])))
+    except:
+        print("Bus I/O Error. ATMega328 may not be powered up.")