In preparation for a robot workshop I ordered a bunch of Arduino Motor Controller Shields. These are super cheap from china, and can drive up to 4 DC motors. They also break out a couple of pins on servo headers, so they're ideal for getting kids to actually assemble and program a robot.
A few weeks later a brown box arrived with the expected customs declaration "other electronic components". These turn up quite regularly here at Sniff Manor, and with the workshop still a month or so away I put the box to one side "for later inspection". As a bunch of "more interesting" stuff turned up, the box sat for a few days without attracting much attention, before I figured I should put it away in the big box of parts I'll need for the workshop. However before putting it away I thought I best check that it was in fact the motor controllers - I do sometimes order stuff and then forget I ordered them...
In this case it was just as well as while the box did contain Arduino shields, they weren't the one I expected. Someone working on a packing line several thousand miles away, had sent me the correct number of the wrong part. They were superficially similar but completely not what I wanted.
A quick search revealed that I'd been sent a bunch of "Multifunction" shields. I then quickly ordered a new set of motor shields (should be here in time!), before deciding there really was no point in sending back the multifunction shields - for what the whole batch cost it wasn't worth the hassle of trying to get them replaced with the right thing. Besides - a new component to play with!!!
The Multifunction shield is a but of a mash up (as its name suggests), which I guess is aimed at beginners wanting quick and easy way to hook up a load of components and start programming them. Unfortunately like many Arduino shields, documentation is scarce, but some searching did turn up an circuit diagram, and some sample code - all written in Chinese. Working through these, and a bit of poking with a multi-meter, I was I was able to get the board up and running.
make led1 digital output 13
make led2 digital output 12
make led3 digital output 11
make led4 digital output 10
make button1 digital input A1
make button2 digital input A2
make button3 digital input A3
when start
.set led1 to on
.set led2 to on
.set led3 to on
.set led4 to on
.
.forever if not button1
..set led1 to off
..wait 0.2 secs
..set led1 to on
..
..set led2 to off
..wait 0.2 secs
..set led2 to on
..
..set led3 to off
..wait 0.2 secs
..set led3 to on
..
..set led4 to off
..wait 0.2 secs
..set led4 to on
The first and simplest things to tackle are the 3 switches and 4 LEDS. Which are attached to the pins of the Arduino, as outlined in this code. The switches have pull-up resistors attached (which you can disable by removing J2, though that still leaves the pins connected together by 10K resistors, and in any case the pins aren't broken out elsewhere, so really not much use). However they are pull-UP's, which mean that pressing the switch generates logic low. Similarly the LED's are also active low - not ideal in a board that's supposed to appeal to newbies: set led to on, turns it off, and set led to off turns it on! There's no reason to design a board this way, and while many "real" circuits are active low its enough to make me hesitate in using this with kids.
make buzzer digital output 3
when start
.forever
..if not button3
...set buzzer to off
..else
...set buzzer to on
The next component we'll look at is the buzzer. Note that this is a buzzer, which makes a very loud, fixed pitch beep, rather than a piezo transducer found on the pibrella. That means its easy to code - we just run it on and off using pin 3 (though again its active low).
make pot analog input A0
when start
.forever
..set message to [ pot *10 ]
..wait 0.1 secs
The blue rectangular block is a 10k pot, set up as a potential divider on A0. While pots can make great user input devices, this one uses a tiny screw, which requires many turns to change it. It's handy for demonstrating the idea, but something a bit bigger, and perhaps with less turns would have fitted the purpose of demo'ing analog input a bit better.
make segLatch digital output 4
make segClock digital output 7
make segData digital output 8
Perhaps the most useful feature of the board is the set of 4x7 segment displays. These are attached to three pins: clock, data and latch. These are the sort of thing we could write a "device" for, but its actually not that hard to program them directly in Sniff.
make segVal number
when shiftOut
.repeat 8
..if segVal > 127
...set segData to on
...set segVal to segVal-128
..else
...set segData to off
..
..set segVal to segVal*2
..
..set segClock to on
..set segClock to off
This is the low level code which loads a byte into the 7 segment display registers. To display a character we first load in a byte showing which segments should be illuminated, and then a second byte turning on (usually) one of the digits. Only one of the digits is actually lit up at a time, but we can keep cycling and it will look fine.
make digit number
make digitVal number
make decimalP boolean
when showDigit
.set segVal to 255
.if digitVal=0
..set segVal to 192
.if digitVal=1
..set segVal to 249
.if digitVal=2
..set segVal to 164
.if digitVal=3
..set segVal to 176
.if digitVal=4
..set segVal to 153
.if digitVal=5
..set segVal to 146
.if digitVal=6
..set segVal to 130
.if digitVal=7
..set segVal to 248
.if digitVal=8
..set segVal to 128
.if digitVal=9
..set segVal to 144
.
.if decimalP
..change segVal by -128
.
.set segLatch to off
.broadcast shiftOut and wait
.if digit=1
..set segVal to 241
.if digit=2
..set segVal to 242
.if digit=3
..set segVal to 244
.if digit=4
..set segVal to 248
.broadcast shiftOut and wait
.set segLatch to on
.wait 2 millisecs
This code shifts out the two bytes representing a number (from 0-9) and displays it on the selected digit, optionally setting the decimal point.
make message string
when start
.make index number
.make doneDP boolean
.forever
..set index to 1
..set doneDP to no
..repeat 4 using digit
...set digitVal to value of letter index of message
...set decimalP to no
...if index=length of message and not doneDP
....set decimalP to yes
...change index by 1
...if letter index of message ="."
....set decimalP to yes
....set doneDP to yes
....change index by 1
...broadcast showDigit and wait
Finally here's the code that goes through the string message, and sends 1 digit of it at a time to the display. The tricky part here is handling the decimal point. If we're displaying a number, and the next character is a decimal point then we display the point with this digit, and skip over the next character. When we get to the end of the string we print a point if we haven't already, and pad with zero's.
In the C examples that I found for the board the code has to keep calling display in the main loop to keep the lcd updated - remember only one set of segements is lit at once, so we need to constantly keep refreshing the display. Fortunatly Sniff can handle this more easily by just running this script when the program starts. It keeps going forever, updating the display in the background. Earlier we wrote a script which reads a value from the pot and assigns it to the string message. Now this is constantly displayed on the LED display.
In fact because the Sniff scripts that make up a program can all run at the same time, we can run the code for the pot, the display, the leds, and the buzzer all at the same time, in a single demo, rather than writing a demo for each feature!
In addition to the built in devices on the boardthere are breakout pins and sockets intended for various purposes.
make servo1 digital output 5
make servo2 digital output 6
make servo3 digital output 9
make servo4 digital output A5
There are four 0v/5v/Signal servo headers. Of course to use them with servo's you would make them digital outputs, but they can equally be used as inputs (and/or analog if the pin supports it).
The block of 7 header in the top left has 0/5v on the first two pins, and serial (Arduino pins 0 and 1) on two of the others.
make irSensor receiveIR device 2
#make lm35 analog input A4
make thermometer ds18 device A4
The block of 6 pins across the middle is designed of attaching an IR receiver on pin 2 in the first three holes, and a temperature sensor on A4 in the second. From left to right the pin out is D2,0V,5V (for theIR receiver) then 0V,A4,5V for the temperature sensor. The temperature sensor can be an LM35, or a ds1820. In the case of the DS1820 J1 provides the required 10K pull-up on the data line - it can/should be removed it you're using A4 for something else. Both a TSOP4838 IR receiver, and a DS1820 should just plug straight in. Though its not obvious there are little white outlines on the board - match the shape, to know which way around.
So that's the technical spec's of the board. The buttons, display, and servo header pins are all pretty useful, as together these have the potential to work well for a range of experiments, the negative logic is annoying in a beginners board. It's also a shame that i2c isn't broken out. I know that's advanced for the target audience, but this would give access a bunch of sensors, which could simply be read, and displayed on the 7 segment display - instant win! A4 and A5 are broken out and unused, but in different parts of the board, so it would be messy (you could install a breakout/io shield underneath just to get i2c, but really?).
I could definitely see then being useful in a workshop. Give me a few days, and I'll post some examples of using the board to do something fun!
I could definitely see then being useful in a workshop. Give me a few days, and I'll post some examples of using the board to do something fun!
Hi, I know it's not quite sniff, but I've developed some real world examples for this shield, which can be seen on this short video clip:
ReplyDeletehttps://youtu.be/BIhI29Pi5zI
You'd be free to convert the code to the sniff equivalent.
where can I get the Funduino Library?
ReplyDeleteCool you write, the information is very good and interesting, I'll give you a link to my site. Zemits
ReplyDelete