Adding analog input to the Pi using the Digispark
Seen and Not Seen
The Digispark has six digital input/output pins numbered 0 to 5 along its top edge (from left to right with the USB connector pointed away from you). Four of those pins can also act as analog input ports, and the best pin to use is P2/A1. Table 1 shows the correspondence between digital and analog pins.
Tabelle 1
Digispark Digital/Analog Pins
Digital | Analog |
---|---|
P0 |
– |
P1 |
– |
P2 |
A1 |
P3 |
A3 |
P4 |
A2 |
P5 |
A0 |
A simple example that uses a Digispark (as opposed to a Digispark plus a Raspberry Pi) and a few of the components you'll need in the final project illustrates how the analog input works, which is what you'll be interested in later. The first bit you'll need is a potentiometer, which you'll use to regulate the blinking speed of an LED. A potentiometer (Figure 3) is a variable resistor, meaning you can regulate the voltage it outputs with a movable part, usually a knob or slide.

The most interesting wire in Figure 3 is the yellow one in the center, which outputs the modulated voltage that changes when you twist the knob, and it is what you want to measure on your analog pin. The illustration in Figure 4 shows you how to hook the potentiometer to the Digispark. The red wire is connected to the 5V output the Digispark supplies, the black wire is connected to Digispark's ground, and the yellow wire is connected to P2/A1. An LED is connected to P0.
Once you've hooked everything up as shown in the diagram, open the Digispark Arduino IDE and enter the "sketch" (Arduino code) you see in Listing 2. Upload it to the Digispark by clicking on the Upload icon in the toolbar. When you see the message saying the sketch has been uploaded successfully, wait a few seconds until the LED starts blinking, then twiddle the dial on the potentiometer.
Listing 2
Variable Blinking
01 int sensorValue=0; 02 03 void setup() 04 { 05 pinMode(0, OUTPUT); 06 } 07 08 void loop() 09 { 10 sensorValue = analogRead(1); // Which corresponds to P2 11 12 digitalWrite(0, HIGH); 13 delay(sensorValue); 14 digitalWrite(0, LOW); 15 delay(sensorValue); 16 }
The farther counterclockwise you turn it, the slower the LED blinks. If you turn the knob clockwise, the LED blinks faster. That's because you are using the variable sensorValue
to set the delay (lines 13 and 15), and in line 10 you are reading sensorValue
off analog pin 1 (digital pin 2), the pin to which the potentiometer is connected. The values supplied by analog pin 1 vary between 0 and 1023, and the delay is measured in milliseconds. When you turn the knob all the way clockwise, you will experience virtually no delay, but when you turn it all the way counterclockwise, the delay is slightly longer than a second.
Dream Operator
To move on to the "safe" project, you need the Digispark to interact with the Raspberry Pi. To do that, you need to include a special library in your Digispark sketch called DigiUSB.h
(Listing 3, line 1). This library is included by default with the Digispark setup, so if you have followed the installation described above, it should just work.
Listing 3
Potentiometer.ino
01 #include <DigiUSB.h> 02 03 int sensorValue=0; 04 int oldSensorValue=0; 05 06 void setup() 07 { 08 DigiUSB.begin(); 09 } 10 11 void loop() 12 { 13 sensorValue = analogRead(1); 14 sensorValue = map(sensorValue, 0, 1023, 0, 9); 15 16 if (sensorValue != oldSensorValue) 17 { 18 DigiUSB.println(sensorValue); 19 } 20 21 oldSensorValue = sensorValue; 22 DigiUSB.delay(10); 23 }
Line 8 initializes communication over USB. This is when the Digispark will show up as an input/output device by reporting its bus and device ID. As before, you read in the value from the potentiometer, again connected to analog pin 1 (line 13), and then make it more manageable by mapping its value from 0 to 9 (line 14).
With map()
, the original value of sensorValue
(i.e., a number between 0 and 1023) is transposed to a scale that goes from 0 to 9. If sensorValue
equals 0 on line 13, it will equal 0 on line 14. If it equals 1023 on line 13, it will equal 9 on line 14. If it equals anything in between on line 13, it will be adjusted proportionately to a number between 0 and 9 on line 14.
Because you don't want to send a constant stream over the USB channel, line 16 checks whether the value has changed since the last time you looked. If it has, line 18 prints it to the USB. The current sensor value becomes the old sensor value (line 21) and waits for a 100th of a second before going again. If you don't include the pause, you are guaranteed to confuse your USB system on the receiving end (i.e., on the Pi), and you will lose your connection with the Digispark.
Now, you can move your other computer over to your Pi, because the next step is to get the Pi to read the values the Digispark is sending over the USB and use them to build up a combination of numbers (e.g., several numbers from 0 to 9), compare it to a combination stored in the Pi's program, and then switch on one LED or another (Listing 4).
Listing 4
Combination.py
01 import sys, time 02 import RPi.GPIO as GPIO 03 from datetime import datetime, timedelta 04 05 # Digispark specific 06 import usb # 1.0, *NOT* 0.4: use *pip install pyusb* to install 07 from arduino.usbdevice import ArduinoUsbDevice 08 09 combo = [] 10 master_Combo = [] 11 red_LED = 24 12 green_LED = 25 13 14 GPIO.cleanup() 15 GPIO.setmode(GPIO.BCM) 16 GPIO.setup(red_LED, GPIO.OUT) 17 GPIO.setup(green_LED, GPIO.OUT) 18 19 def readCombo(): 20 21 v_combo = [] 22 fb_store='0' 23 24 while True: 25 try: 26 theDevice = ArduinoUsbDevice(idVendor=0x16c0, idProduct=0x05df) 27 28 except: 29 print "Dial not found! Attach your Digispark (with a dial) and rerun." 30 GPIO.cleanup() 31 sys.exit(0) 32 33 try: 34 feedback="" 35 while True: 36 lastChar=chr(theDevice.read()) 37 if lastChar=="\n": break 38 feedback=feedback+lastChar 39 40 print(feedback) # Comment this line in production 41 fb_store=feedback[0] 42 43 start_time=datetime.now() 44 45 except: 46 # Check if time on number is greater than 5 seconds 47 48 try: 49 elapsed_time=datetime.now()-start_time 50 if elapsed_time.seconds > 5: 51 v_combo.append(fb_store) 52 blinkLED(green_LED, 2, 0.2) 53 start_time=datetime.now() 54 55 if len(v_combo)==len(master_Combo): break 56 57 except: 58 time.sleep(0.1) 59 60 return v_combo 61 62 def blinkLED(v_LED, times, speed): 63 64 GPIO.output(v_LED, GPIO.LOW) 65 for i in range(times): 66 GPIO.output(v_LED, GPIO.HIGH) 67 time.sleep(speed) 68 GPIO.output(v_LED, GPIO.LOW) 69 time.sleep(speed) 70 71 if __name__ == "__main__": 72 73 if len(sys.argv)==1: 74 print "Please input code combination." 75 76 else: 77 78 # Read combo from command line 79 master_Combo=sys.argv[1:] 80 81 while True: 82 combo=readCombo() 83 if combo==master_Combo: 84 blinkLED(green_LED, 3, 0.3) 85 break 86 87 else: 88 blinkLED(red_LED, 3, 0.3) 89 90 GPIO.cleanup()
To begin, you need to do some housework by importing the modules you'll need later (lines 1 to 3). The most interesting module is RPi.GPIO
, a module preinstalled in Raspbian that supplies code to read from and write to the Raspberry Pi GPIO pins. Line 6 brings in the Python USB module. This module is not usually installed by default, so you'll have to install it by hand; however, DO NOT use apt-get
. In most Linux repositories, including those that Raspbian uses, the version of PyUSB available is the old 0.4 version. This will not work with your program; you're going to need the new 1.0 version.
Next, you need to install pip
, the Python package manager, then you can install PyUSB using pip
:
$ sudo apt-get install python-pip $ sudo pip install pyusb
These commands grab and download the latest version of PyUSB from the main Python repositories. Line 7 brings in a Digispark-specific module. Again, this will not be installed on your system by default, so you'll have to install it manually. To get the module, clone the DigisparkExamplePrograms
directory from the Digispark GitHub account into your directory:
$ git clone https://github.com/digistump/DigisparkExamplePrograms.git
and copy, move, or link the DigisparkExamplePrograms/Python/DigiBlink/source/arduino/
subdirectory to the directory from which you want to run your own program (your working directory). For example, if you cloned DigisparkExamplePrograms/ … into your working directory, cd
into it and enter
$ ln -s DigisparkExamplePrograms/Python/DigiBlink/source/arduino
which creates a link to the arduino
directory containing the module within your working directory.
From lines 9 to 17, the program continues with the housework, setting variables and making sure the GPIOs are ready to be used. You'll be hooking the red LED up to pin 24 (line 11) and the green LED to pin 25 (line 12). Note that you'll have to run this program as superuser (with sudo
) because regular users don't have access to the Pi's GPIO interface.
Down in the main
section (lines 71 on), you read in the master combination as arguments to the program entered on the command line. Clip off the first element of sys.argv
in line 73; it's the name of the program (see the "sys.argv" sidebar). If you want the master_Combo
to contain, say, ['1', '2', '3', '4']
, you'd call the program like so:
$ sudo python combination.py 1 2 3 4
Although the combination may contain as many numbers as you like, they must all fall between 0 and 9, as was established in Potentiometer.ino
(Listing 3).
sys.argv
Elements of a command entered at the command line are kept in a list (array) called sys.argv
. The first item of the list is the program invoked at the command line. The next items in the list are any arguments entered after the program name. Because array numbering starts at zero, the elements of the sys.argv
array are numbered [0]
, [1]
, [2]
, and so on. If you want the arguments to the command, you take from element [1]
until the end of the array, as in Listing 4, line 79.
Next, an infinite loop (line 81) reads in the user's combination (combo
) using the readCombo()
function (I'll discuss this function in detail in a minute) and compares both the user's combo
and the master_Combo
defined when the program was run. If they are the same, the program blinks the green LED three times (line 84) using the blinkLED()
function (lines 62-69) and exits the loop, ending the program. If the combination is not correct (line 87) the program flashes the red LED and goes through the loop again.
The blinkLED
function takes three parameters: the LED to flash, the number of times it is flashed, and the speed at which it is flashed, Much more interesting is readCombo
function (lines 19-60). This function reads in the combination from the potentiometer attached to the Digispark. When it's first called, it ignores the state of the potentiometer until the dial is twiddled. When the user finally turns the dial, it starts reading the input and waits until the user chooses a number. If the user stays on a certain number more than five seconds, the program assumes that is number selected as part of the combination and appends it to v_combo
.
The program indicates a number has been accepted as part of the combination by blinking the green LED twice. The function runs through this routine as many times as there are numbers in master_Combo
. When done, the routine exits the loop and returns control to the main
function, where the combination entered by the user (combo
) is compared with the combination entered by the operator (main_Combo
), as already discussed.
Buy this article as PDF
Pages: 8
(incl. VAT)