Author Archives: ghp_Ar7p

RFID Tag Reader

There are nice little tag reader devices available from ‘innovations’ as the ID-12LA. It works with the 125kHz cards or tags, does not need an external antenna and can work directly with Raspberry Pi. I recently got one on my desk and connected it to scratch.

For the setup, there is the possibility to connect it directly to Raspberry Pi serial port, or to buy an usb-adapter. I have choosen the simple way, but as the pin spacing is 2mm there is a breakout board needed to match a breadboard. I used some 2mm spaced sockets on the adapters and have the module pluggable.

The two images show the breakout board without the modue and with the module. The yellow LED at the right is a ‘always on light’ used as a power indicator. Quite useful to see if a breadboard is connected.

rfid-setup_0

rfid-setup

For the connection to scratch a special adapter is needed for scratchClient. The adapter.serialAdapter.RFID_Reader_Adapter opens the serial port and extracts the Tag-Numbers from the byte stream. When data are available, these are sent to scratch. Then a broadcast event is published ‘rfid_available’. A sample config file is provided config/config_ID12LA.xml.

ScratchClient start is performed by

sudo python src/scratchClient.py -c config/config_ID12LA.xml

Start scratch 1.4, open ‘remote sensor connections’. When a tag or card is near the reader, then scratch should receive a variable ‘rfid’ containing a 10 bytes hex number.
sensor2

A sample program can record tags and associated names in an internal ‘database’, build from two lists. One list is for names, the other for rfid.

rfid_handler_menu

select ‘register’ to read in tags and names (from keyboard).

rfid_handler_record

In ‘run’-screen, tags scanned are checked against the available rfid in rfids-list. When match exist, the cat tells the name found.

rfid_handler_run

The green/blue boxes are an indicator for read events. For each event, it should turn clockwise.

The ‘clear data’-Button clears internal data.

And for all the impatient people there is a simulation mode which populates the database with some dummy values. In run mode, the simulation displays a ‘random’-button which simulates input.

scratchClient can also be used to provide input to scratch. Open http://localhost:8080 and navigate to ‘adapters’.

scratchClient_adapters

on the right hand side, there is lat value for rfid shown. The Quotes are mandatory here, as scratch needs to interpret values as strings. Click into the text field, you get an entry popup.

scratchClient_adapters_entry

Confirm the entry by ‘enter’. Then click on the rfid_available- string and a red blink rectangle confirms the event is sent to scratch.

The formatting of the class name in the adapter box is not perfect, will change this if there is some spare time.

One feature in the scratch code is how the simulation data insertion is solved. It is not possible to overwrite sensor values. So when sensor values arrive, the data are copied to a global variable and a new broadcast is issued.

In the stage scripts, the input from the sensor is copied to a globale variable.

script

All code processing rfid data is based on ‘rfidValue’ and ‘rfid_for_processing’.

In the rButton-script, this global variable and event is produced.random

Downloads

scratchClient

scratch sample program

Arduino UNO, NANO connected to Scratch

Arduino UNO has an USB connection, which supports serial connection to a host computer. The arduino can be used as a IO expander, connecting digital io lines, pwm, servo or adc-inputs directly to scratchClient and to scratch.
On digital inputs D2-D12, the firmware supports counters. The inputs are debounced  and frequencies are possible till prox 50Hz.

This setup with scratchClient can be run on Raspberry or on windows, unless scratch 1.4 is used.

Powered by the USB-connection, the UNO provides 5V-compatible inputs/outputs. This is an advantage in some constellations. But do not connect these outputs directly back to the raspberry GPIO pins. And be careful on power consumption. Small servo can be operated, but larger current devices need external 5V supply.

The solution is also applicable to arduino NANO. This small board offers a breadboard friendly layout.

nano_breadboard

Sample setup with a NANO, 3 LED, Poti, Button, Servo and NANO on breadboard. Host computer (Raspberry Pi or Windows) not shown.

The functionality presented here is not a bridge to mesh network, propagating events and sensor updates into the arduino. There is a custom arduino sketch needed which only exposes the IO resources, but does not allow for additional logic in arduino (yet).

Configuration of the io-pins (direction, pullup, pwm, servo) and adc-pins (whether used or void) is controlled by scratchClient through configuration.
The scratch names used are configurable in configuration too. This is common functionality of the framework.

Communication between host computer and arduino is by a serial line USB connection.  Speed is 115200 bd, set line end to LF . The arduino protocol uses as short as possible command sequences.
Example:
pwm:4,90\n  sets PWM channel 4 to 90.
p:4,90\n is the same command, abbreviated.

With
help\n
a summary of command features can be printed.

The protocol is build on readable ascii sequences, which makes debugging with arduino serial monitor easy (set line end feature to ‘newline’). This also allows to fully drive the protocol from the serial console.

The command parser uses a state based approach for speed purpose. Each received char needs to be processed as quick as possible, which is only possible with a state machine.
First implementation was collecting chars in buffers and on a LF-char the data have been compared to the different commands. This needed many expensive strcmp-operations, decoding the parameters was done by sscanf. This approach limited throughput.

The parser code is generated by a python program and the resulting code is then inserted into the arduino C-program.

The code for arduino, sample configuration for scratchClient and sample scratch program is in the scratchClient distribution.

For setup, follow the steps described below.

Step 1, program the firmware to arduino

Start arduino IDE software, load arduino/arduinoUno/arduinoUno.ino from the scratchClient distribution and program it into the UNO or NANO. This needs to be done only once. I run this from a windows machine, but arduino IDE should also be supported on Raspberry Pi.

The LED13 on the arduino should blink at 5Hz, quite fast. This indicates that the firmware is running, but did not yet receive configuration.
On a serial monitor, you should see:

arduino sending@115200 Bd
arduinoUno, version 2016-02-21
config?
config?
config?

The config?-request is printed each second until the host provides configuration commands. Close serial monitor in order to allow scratchClient to have access to the serial line.

With ‘help’ from the serial monitor (use newline for line end separator), the arduino provides the list of supported commands.

Step 2, sample Hardware setup

arduinoUno_Steckplatine

The hardware uses a potentiometer (2k to 10k are ok) on AD0. On D3, there is a button connected. The other side is having a 1k-resistor to GND (just in case the output is configured as an output, this prevents damage to the IO).
Two LED are for output. The green LED is on a PWM-output D5, so it can be dimmed.

This setup is a sample. The functionality of all the inputs and outputs are defined by configuration in scratchClient. See config/config_arduino_uno.xml for a sample.

Step 3, connect arduino with USB-Line to RaspberryPi or windows computer.

On raspberry, lookup /dev /tty* connections and configure the UNO serial device in config/config_arduino_uno.xml-File.

For windows, you see the COMn-Device used in deviceManager. Configure this name in config file.

An arduino UNO or NANO needs a few 20mA when running,  LEDs add prox 10mA each. This current is provided by USB port of host computer. If more power is needed, then an external power supply is needed.

Step 4, start scratchClient with configuration

cd ~/scratchClient
python src/scratchClient -c config/config_arduino_uno.xml

After a short while, the LED13 should start blinking at 0.5Hz, quite slow. This indicates that configuration was downloaded and system ready to be used. The Tx, Rx-LED on arduino should flash now and then. Quite often when you turn the potentiometer, or when you press the button.

Step 5, start scratch with sample program

There is a sample program in scratch/arduinoUno/arduino.sb

scratch

The program takes the button input and controls the red LED with it.
The value from the potentiometer is used to set the pwm-rate and dims the green LED. The mapping of the variable names or sensor names to IO-points is done in config file.

ID-Code

The arduino can have an ID-code in eeprom, which can be set by serial line console and read out from remote. This ID allows the host raspberry to recognize the arduino and provide configuration for this special device. This is a very nice feature for school setups where some experiments are hard wired and need fixed configuration. There is a starter code available which checks the connected arduino, and presents the related config files for scratchClient to start. I am working on an extension to start scratch with a basic program too. Avoids a lot of handling errors in school, especially where the focus is on driving an experiment and coding is not so important.

The serial protocol allows to read and set the ident code.

cident?\n     request idcode
cident:<char16>\n write idcode

Configuration Tool

The setup of the xml config file is not very intuitive. There is a config gui available to edit the file. The tool is started with

cd ~/scratchClient/tools
java -jar scratchClientConfig.jar

scratchclientconfig

The left side of the frame is the editor pane which allows to select the various functions for the arduino. The right panel is a view-only display of resulting xml data.

Existing files can be loaded, but current version (2017-02-10) only allows to handle one adapter of type ‘UNO_Adapter’.

Constraints

The adc-channel is limited to 10Hz update rate. There is averaging for three samples per measurement value transmitted.
The digital inputs are limited to 20Hz update rate.
The adc-channel of atmel328 allow for analog inputs or GPIO usage.
PWM pulses are created with arduino native analog_write on the digital pins. Value range for pwm are 0..255.
Servo pulses are created with Servo-library. See limitations of this library in Arduino Servo [https://www.arduino.cc/en/reference/servo]. Input values for servo are 0..180.
Configuration is not persisted in the arduino (but downloaded from the the scratchClient adapter); there is no interface for custom logic (for fast sensors).
Configuration is requested to be sent from PI or windows to arduino on reset of arduino. If scratchClient configuration is changing, then a reset of arduino is needed to make this active. As in most cases a hardware change is made with arduino disconnected from power (either USB cable or power plug), this is only a small limitation.

This scratchClient adapter runs also on windows platform. This allows setups where a windows computer, scratch 1.4 for windows are using IO connections.

Other libraries

Recently I discovered ‘nanpy’, a python library to control an arduino by python programs.

Updates

Updated 2017-03-15, Counter for digital inputs added.
Updated 2017-02-10, Config tool for xml config file included.
Updated 2016-02-21, Some remarks on state based parser, command sets.
Updated 2016-02-15, added servo capability.

aScratchPangoFont-Problem in ’14-Jan-15′ scratch

Remark: For raspbian ‘jessie’ and scratch “Scratch 1.4 (linux) of 2015-09-15”, this problem is solved.

In scratch “Scratch 1.4 of 14-Jan-15”, as provided in raspbian for Raspberry Pi, there is a serious bug which prevents projects from loading. This affects scratch projects which are stored/reloaded multiple times, and only scratch projects which use texts in new created sprite costumes. The error popup is “primSetFont:size:bold:italic:antialias: failed”

error

Problem description

When loading a project, occasionally the following problem occurs

pango_001

The error message is “primSetFont”.

Reproduce the problem

In a new project, create a new sprite with the edit-button. Add a text to this sprite. Close the editor and save the project –> “x00”. Close scratch.

Start scratch, open project “x00”.
Open the costume with the font,, click to the ‘T’ext button. There is “a ScratchPan…” displayed. Close editor with ‘cancel’. Save project as “x01”. Close scratch.

Start scratch, open project “x01”, save as “x02”. Close scratch.
Repeat this till you reach “x05”. When loading “x05”, you should get this problem.

Technical Details

When looking to the project.sb-file of an affected project, there is a sequence shown where the original ‘DejaVu’-Font is wrapped into a ‘s ScratchPangoFont’ multiple times.
This wrapping seems to occur each time on save, and after a few times the length exceeds some limit. This happens with all fonts, I found no exceptions.

sb

project.sb file in a plain text editor.

Error handling

When nothing important is in the project, just discard it.

When nothing important is in a costume, just discard it.

When work needs to be restored, click to the ‘proceed’-Button in the error messages. When one error message is away, there are quite a lot new of them might pop up. Always click ‘proceed’.

Then, look for background or sprites where fonts are used. You see it in the thumbnail preview in the costume tab.

‘edit’ these costumes. The editor has problems to start, and you get again many of these popups. pango_002

pango_003

Editor window is displayed slowly, when it is back till you see the title bar of the editor “Paint Editor”, drag it around a little bit and the editor window will be redrawn to its usual appearance. Click to the ‘font’ button, this is the “T”-Button.

pango_004

You see  ‘a ScratchPan..’ in the font selector. Select a font from the selector. This clears the false value in this field. Commit the work with ‘ok’.

The sprite or background is restored. Now go ahead with the workaround procedure.

Workaround Procedure

Completed projects

If a project is completed, just avoid to save the project when leaving.

Projects during development

If the insertion of text is needed to costumes, then
– finalize the costume/background as usual.
– export the costume to a file. Right click on the thumbnail image and ‘export this costume’.

pango_007

Then, use the import function and load this file into the costumes. The difference is that this is a bitmap copy, not containing the font. The problem is, that editing the text is no longer possible.
Delete the costume with the font.

 Comments

There is also an error report on raspberrypi-Forum. Leave a comment there.

RaspberrPi forum

 

Deployment of code from eclipse to a Raspberry Pi

I usually write my code, either java, python or c++ in eclipse on a laptop or desktop computer. Eclipse is very comfortable, but unfortunately too large to run on these small target systems.
So I had the need to deploy the code to a remote system.

Deployment can be done manually, when a few files are transferred by a ftp tool.

But when complexity gets larger (omit some files, different target systems), or frequency of deployment is high (many per day), automation is needed.

Apache ‘ant’ is a scripting tool which allows to package, transfer and remotely deploy software.
Ant from ant.apache.org is a build system based on a xml syntax, which aims to run on almost every operating system where java is available. It is widely used in professional software development in industry.
Eclipse comes with ant preconfigured, at least if you download the java edition and then add the c or python or whatever plugins.

In all my projects, an ant build file ‘build.xml’ is in the project root. There I provide targets for version control, backup and deployment. See here a snippet from the build.xml for my scratchClient. The detail is about deployment here.

<project name='scratchClient' default='distribute'>
   <!-- build.properties provides connections and passwords -->
   <property file='../build/build.properties' />

   <!-- filesets define 'what' to transfer -->
   <fileset dir='../' id="tar.fileset">
      <include name='scratchClient/**/*' />

      <!-- in some configurations, there are phone numbers, pin or alike, exclude from deployment */
      <exclude name='scratchClient/**/private/**/*' />

      <exclude name='scratchClient/build.xml' />
      <exclude name='scratchClient/build.properties.template' />
      <exclude name='scratchClient/*pid' />
      <exclude name='scratchClient/**/*pyc' />
      <exclude name='scratchClient/build.properties' />
      <exclude name='scratchClient/download/**/*' />
      <exclude name='scratchClient/temp/**/*' />
      <exclude name='scratchClient/.settings/**/*' />
      <exclude name='scratchClient/.project' />
      <exclude name='scratchClient/.pydevproject' />
   </fileset>

   <target name='deploy'>
      <echo>deploy to ${pi.host}</echo>
      <echo>from  ${basedir}</echo>
     
      <delete file="download/scratchClient.tar.gz" failonerror="no" />
      
      <tar destfile="download/scratchClient.tar.gz" compression="gzip" >
         <fileset refid="tar.fileset" />
      </tar>

      <echo>send app code  /home/pi/scratchClient  ${pi.user}@${pi.host}:/home/pi</echo>

      <scp file="download/scratchClient.tar.gz" password="${pi.password}" todir="${pi.user}@${pi.host}:/home/pi" trust="true" />

      <sshexec command="rm -R /home/pi/scratchClient/*" 
               host="${pi.host}" username="${pi.user}" password="${pi.password}" 
               trust="true" failonerror="false" />
      <sshexec command="tar zxvf scratchClient.tar.gz" 
               host="${pi.host}" username="${pi.user}" password="${pi.password}" 
               trust="true" failonerror="true" />
   </target>

The script packages the code in a temp folder (not adding some common stuff). Then it sends (scp) it to the target machine, wipes the target folder (sshexec) and unpacks the data there. sshexec is connecting to the remote computer and executing commands there.

In eclipse, this script is activated by a rightclick in an outline view, but can also be activated on a eclipse build procedure.

The host names, passwords for the target environment is in another build script build/build.properties
One reason is that these are common for many projects, the other is that these are outside the usual scope and when copying a bunch of data and sending them away these security related things will not be included.
This file looks like:

#Sun, 17 Mar 2013 08:33:21 +0100
pi.host=192.168.2.105
pi.user=pi
pi.password=NNNNNNNNNNNNNNN
root.user=root
root.password=NNNNNNNNNNNNNNN

This is a complex setup, but reliable and I have full control on what happens.

Except for a ssh-access on the raspberry pi, there is no extra deployment software needed.

scratchClient and piGlow

piGlow is a nice little board, providing 18 colored LED with an I2C-Controller.

With a major rework of the i2c-part of the scratchClient framework, I added support for this board / device in scratchClient.

Start it with

cd ~/scratchClient
sudo python src/scratchClient.py -c config/config_SN3218.xml 

The configuration uses some common variables to update the pwm-values in sync for all, for the ‘branches’ and – of course – the individual LED.
In the distribution, there is a simple scratch program, just providing variable definitions and some watchers on stage with sliders.
piglow_scratch

Not very graphic, I agree. But hopefully it saves some time in creating these 18 variable names (plus some more). It is in scratchClient/scratch/SN3218/piglow.sb

The branches are group names for the three wings arranged on the board.

piglow_annotated

The above sketch shows the piglow board in action, annotated with the channel numbers in hex.

As indicated on the package of piGlow, the LED can be VERY bright when full power is applied. Looking into these light could harm your eyes.

But there is a trick to project an image of the LED to a remote screen (or the ceiling of my room).
Use a magnifying glass or an objective lens.
lupe

When adjusting the setup, be sure NOT to have the LED at full brightness.

aufbau

Place the lens in the correct distance in front of piGlow. I first tried out which distance is needed by hand, and then fine tuned the focus by adding sheets of paper. It was needed to place the lens in a stable position for the photograph.

result
The result on the ceiling, prox 0.3m large, 1.6m away. The dark grey structured background is the white ceiling, outshined by the image of the LED.

The center LED are opaque, the other LED show the bright chip inside the small package. The image in this setup was 15 times enlarged.
Again: never look into the bright light directly.

 

scratchClient and piFace

piFace uses MCP23S17-chip, which is supported by scratchClient.

The chip is a 16bit port expander; in piFace one group is used as an input, the other group of 8 bits are used as outputs, connected to a open collector driver.
One of the interrupt pins of the chip ‘intB’ is connected to  GPIO25. This is not used by scratchClient (but does not allow to use this pin for other purpose.

The hardware setup: two LED, a green one and red one, and a small motor powered by a battery and controlled with the relais.

hardware

This post demonstrates the use of scratchClient as a ‘hardware abstraction layer’, assigning meaningful names to scratch variables.

In this example, I connected a red and green LED to piFace.
With default configuration, the default names are ‘out_2’, ‘out_3’.

config_default

Here a sample of a blinking LED, using these definitions.

script_default

This works, but the variable names are not very conclusive. There is the need to keep a record on what this ‘out_2’ is meaning. But scratchClient allows to tweak the configuration files and provide more meaningful names for the variables controlling the hardware.

When editing scratchClient/config/config_mcp23s17.xml, the names of the variables in scratch can be changed. ‘green_led’ and ‘red_led’ are better describing what is connected to the hardware.
config_renamed

Restarting scratchClient is needed when configuration is changed.

Side topic: the ‘all’-variable, common to all outputs here, can be used to set all values immediately to either ‘0’ or ‘1’. Useful for a ’emergency shutdown’ or alike.

With the meaningful names, a scratch script looks like this:
script_renamed

The script gets more expressive. There is no need to map the abstract names to the thing connected.

Another example. Suppose a small motor is connected to relais_1.config_relais

Here, the variables ‘relais_1’, ‘out_1’, ‘all’ can be used to drive this output.

Setting this variable is straightforward, but ‘relais_1’ is not a descriptive name.

script_motor

When editing the configuration, the scratch variable names can be changed to ‘motor’.

config_motor

This changes the names in scratch to  ‘motor’.

script_motor_renamed

The following snippets show the changes: left side are the default definitions, right side the more meaningful names.

variables_default variables_renamed

 

Smartphone positional sensors connected to scratch

In a quite popular computer magazine, c’t 2015-03-07 (heise verlag), there is a nice article about how to connect a smartphone’s positional sensors to a remote server by using a web page, some javascript and websockets.

Starting from this, there was the idea to connect this to scratch (what else ?).

The basic roadmap was
– add a html-page to my scratchClient’s web server, with javascript

var addr = "ws://" + window.location.hostname + ":" + window.location.port + 
           "/pendel";
var websocket = new WebSocket( addr );
 
function handleOrientation(event) {
       var x = event.beta%90;
        var y = event.gamma;
        x += 90;
        y += 90;
          try {
                websocket.send(JSON.stringify( { x:x, y:y }));
            }
            catch(err) {
                // console.log( err.message );
            }
    }
    window.addEventListener('deviceorientation', handleOrientation);

– in scratchClient, there is cherrypy used to serve the web pages. WebSocket was a new feature to be added there.

– an adapter needed to be written adapter.websocket.WebsocketXY_Adapter, receiving the messages and converting them to scratch variable updates.

So far the plan.
Websocket implementation in sandbox environment worked well, but as I use ‘routes’ to dispatch the requests it took some time to find the correct setup.
Next finding was that the connection is really performant, and a slow movement of about a second duration provides a hundred messages flowing into scratchClient. This is far above from what scratch is able to handle.

Filtering out messages is starting in the browser. Rounding values to a tenth of a degree and sending values only on change removes quite a lot of values. After some experiments with timers in my android browser I found no viable solution to throttle update rate. Timers seem not to work in this javascript environment. Next step in filtering is in the adapter, taking most current value each 0.05sec and ignoring intermediate values.
Final step of filtering is inside scratch. When using the ‘glide’-move, scratch will ignore intermediate values. When using the ‘goto’-statement, processor load is getting much higher.

When I have seen webSocket working pretty smart, I removed the ajax-updates and webEvents from/to web browser to server. When working on the server side, some legacy code in editing values in browser was rewritten, the svg-generator is smarter now and the underlying event distribution system in scratchClient was replaced by a publish-subscribe pattern.

Installation of scratchClient now needs ‘ws4py’ in addition to cherrypy. See the docs.

Start scratchClient

cd ~/scratchClient
sudo python src/scratchClient.py -c config/config_websocket_pendel.xml -guiRemote

The guiRemote-switch is needed to allow remote browsers connecting to scratchClient.

In a smartphone browser, navigate to your pi’s address. Of course you need a (wireless) network connection between smartphone and raspberry. In my network, the RaspberryPi’s address is 192.168.2.90, most possibly different for your PI. Use ‘ifconfig’ to look it up.

http://192.168.2.90:8080

Navigate to “Smartphone as Sensor” browser

You should see rectangle with a red/green dot moving around. This is as proposed by the c’t-article.

In scratch, enable remote sensor connections and provide the following script. gotoX and gotoY are sensor values provided by the scratchClient. The xl and yl-Variables are local variables in scratch.

smart

The x and y-values are getting exchanged and the y-value gets inverted to match the coordinates of the smartphone to scratch stage.

And thats it. The sprite moves close to the smartphone movements. There is some small time lag on my PI ModelB (not a pi plus so far), but sufficient good.

Atmel328 firmware for DHT22 Temperature, Humidity

The temperature, humidity sensor DHT22 is a quite inexpensive sensor, well suited for microcontroller applications. It uses same protocol as DHT11.
It is connected by a single wire, needs 5ms for a read cycle, but a quite challenging protocol where the pulse width gives ‘0’ or ‘1’ bit values.

This is a typical application for a coprocessor for raspberrypi. For an atmel328, it is not a challenge to handle this protocol.

atmel_dht22_Steckplatine

The signal from this sensor is relying on exact timing.

dht22_waveform

The initial ‘pulse low’ is not in the chart.

The firmware uses internal timer with 1 us resolution to measure pulse widths. Using the timer unit makes this method insensitive when interrupts produced by SPI communication occur in parallel.

The atmel firmware triggers the data aquisition, and provides a 40bit ‘raw’ result to the raspberry pi host computer. The conversion of the values  to temperature, humidity values is performed in python code. See the sample code provided in the download to see this procedure.

Of course, there is an adapter for scratch.
cd ~/scratchClient
sudo python src/scratchClient.py -c config/config_dht22_atmel328.xml

A detailed description on how to program the firmware is on the download page.

Timer for HC-SR04 ultrasonic sensor and scratch

The ultrasonic sensor HC-SR04 is a quite inexpensive ultrasonic sensor, well suited for microcontroller applications.
It produces pulse width modulation directly giving the signal run time.

For 1.7m, at sound speed in air of 340m/s, you get 10ms pulse width.
Up to now, my scratchClient software had no ability to support this device. In order to evaluate different approaches to measure pulse width timings in this range, I have set up an arduino board simulating this device with 10ms timing.
The goal was to have around 1000 measurements and look for the distribution of values.

Approach A was to take python code as found on the net. Two loops, first one looking for raising pulse and second one looking for falling pulse.

python
Results are not very precise.
There are quite a lot of measurements at 10ms, but 2/3 of all results are up to 40% higher; few also till 16,5 ms. This is as expected, as the IO system is slow, and a lot of other things are running in the system in parallel.
Advantage is that there are no additional cost, except some voltage dividers needed.

Approach B is a microcontroller subsystem using the atmel 328 chip, sitting on a breadboard and connected with SPI to RPI. The internal oscillator is used for simplicity and reduced cost. This setup is similiar to the adc-setup described in another post.
Time measurement is using the 16 bit timer in 1/64 resolution, yielding 8us values.

ultrasonic_328
Results are pretty nice, although the deviation is 3% from 10.0ms. Most possible this is caused by the free running oscillator running a little bit too fast; some more investigation is needed here to eliminate software errors.

The code is polling the timer, which is fast enough for this application. SPI is handled with an interrupt coded in assembler. This allows up to 240kHz SPI frequency.
The software is completed and supports up to 4 sonic sensors.
Cost is prox 3.5$ per unit, some soldering and some voltage dividers. No difficult software setup needed.

I found other approaches on the net. DMA code, C-Code or alike. Problem here is the complicated software setup (no ready to use solutions) and the difficult integration into the python environment with RPI.GPIO.

The hardware setup is straightforward. Note the 5V on the supply voltage of the HC-SR04. Doublecheck also the ground connection from HCSR04 to breadboard and to Raspberry. This is important to avoid to get 5V into the raspberry inputs.

For the scratch setup, there is a sample configuration with device(0) connected.

cd ~/scatchClient
sudo python src/scratchClient.py -c config/config_hcsr04_atmel328.xml

In scratch, enable remote sensor connections. You receive ‘distance_A’.

For detailed instructions on how to program the atmel processor, see the documentation in the download file on download page. The programming is performed by the raspberry pi with the SPI cabling.

MCP23S17 aka piFace supported in scratchClient

The 23S17 is the chip used on piFace, It can be used also on a breadboard, providing 16 extra IO-pins for the raspberry.
The adapter adapter.mcp23s17.MCP23S17_Adapter expands the IO-capabilities by 16 ports, either input or output.

 mcp23s17

On the image you see the breadboard setup with the device 23s17, connected with an adafruit breadboard adapter to raspberry pi. The small boards plugged in vertically contain 8 LED with a resistor array. I use those whenever I need more than one LED on a setup.

Programming details

This adapter was a challenge. It needed a configuration specific for each adapter instance of this type, and this complexity was beyond the available <parameter/>-tags. The decision was to break the configuration phase into multiple steps, where after basic creation and setup of the adapter instance the configuration manager passes control to the adapter and provides the local xml config node in this call. The adapter reads the <io/>-tags, configures the necessary adapter methods for sending and receiving variables and gets the device settings for input, output direction and pullup setup.

Configuration details

The device 23s17 allows to have up to 8 devices ‘in parallel’ on one SPI chip select. These devices have hardwired distinct slave addresses. In the configuration, this slave address must be given.

        <parameter name='spi.bus' value='0' />
        <parameter name='spi.device' value='0' />
        <!-- slave address must match the hard wired slave address on the device -->
        <parameter name='23s17.addr' value='0' />

The IO direction for the port pins is defined by <io/>-tags.

        <io id='GPA0' dir='out' />
        <io id='GPA1' dir='out' />
        <io id='GPA2' dir='out' />
        <io id='GPA3' dir='out' />

        <io id='GPA4' dir='out' />
        <io id='GPA5' dir='out' />
        <io id='GPA6' dir='out' />
        <io id='GPA7' dir='out' />

        <io id='GPB0' dir='in' pullup='none'/>
        <io id='GPB1' dir='in' pullup='none'/>
        <io id='GPB2' dir='in' pullup='none'/>
        <io id='GPB3' dir='in' pullup='none'/>
        
        <io id='GPB4' dir='in' pullup='weak'/>
        <io id='GPB5' dir='in' pullup='weak'/>
        <io id='GPB6' dir='in' pullup='weak'/>
        <io id='GPB7' dir='in' pullup='weak'/>

It is generally a good idea to define all of the port pins. Technically it is needed to define those which are used in the application. The id-values are predefined and must be used as seen here.

For ports defined as dir=’out’ outputs, the corresponding adapter input methods can be used:

        <input_value name='inputGPA4'>
            <!-- variable name is the name of the scratch variable which is 
                 send out to the adapter -->
            <variable name='input_4'/>
        </input_value>

For ports defined as dir=’in’ inputs, the corresponding adapter output methods can be used:

        <output_value name='outputGPB2'>
            <sensor name='output_2'/>
        </output_value>

The variables send out from scratch are ‘0’, ‘1’ to set the output pin of the 23s17 to low, high.

The sensor values received from scratch are ‘0’, ‘1’ for the input pin of the 23s17 receiving low, high.

Start scratchClient

scratchClient startup does not need special considerations.

cd ~/scratchClient
sudo python src/scratchClient.py -C config/config_mcp23s17.xml

The file config/config_mcp23s17.xml is an example of a full functional configuration.