Archive for the ‘Uncategorized’ Category

Moving code from Arduino to Raspberry Pi

Thursday, May 31st, 2012
Photo: Hello world, using the WiringPi library to control an LED display.

Photo 1: Hello world, using the WiringPi library to control an LED display.

To celebrate getting the GPIO working using WiringPi from Gordon Henderson I thought I’d have a quick look at the difference between running some code on an Arduino compared to running almost the same code on a Raspberry Pi (RasPi).

It is worth noting now that the setups I’ve been using to test with are all powered from a separate 3.3V supply with the grounds linked. Nothing is being powered via the RasPi itself to avoid drawing too much current should I make a mistake. When working with the RasPi you should be careful as the RasPi will not take kindly to static discharge, connecting things backwards or the wrong voltage levels.

The really great thing about Gordon’s library is that by using it I am able to transfer Arduino code to the RasPi with only a few simple changes. Obviously not everything in the Arduino libraries are present, but the basic I/O manipulation is plenty for some simple applications.

MAX6675 thermocouple interface example

The MAX6675 from Maxim is an SPI Bus based thermocouple convertor that I built a breakout board for a while back. You can find out more information about that project in this earlier post.

As a simple test I took the basic example from the MAX6675 thermocouple interface library and adapted it to run with the WiringPi library on the RasPi.

I initially ported the example and library to C as the WiringPi was in C and I had a couple of issues compiling mixed C and C++ properly. After a bit of investigation I found that when explicitly including the libraries as C the compiling problems go away. Below is an example of how to modify the wiringPi.h file to ensure it is included as C and not C++. Gordon has said he will make this change to the library on the next release. Once I had sorted out the makefile to use g++ rather than gcc I was able to compile and link successfully.

Listing 1: Explicitly declaring a header file as C


 #ifdef __cplusplus
 extern "C" {
 #endif
  
 // wiringPi.h Code goes Here 
 //  or 
 // #include <wiringPi.h>

 #ifdef __cplusplus
 }
 #endif

While compiling and linking of the example was now okay, the next problem was that when run, the program just exited with a “Segmentation Fault” (segfault). I didn’t even see the error message when running as root with sudo, it was only when running as the standard user (pi) that it became apparent that something was wrong with the software rather than the hardware.

When I had run previous examples as the standard user I would see a permissions related error complaining that the program could not access the “/dev/mem/” device. This error comes from the part of the WiringPi library that sets up memory access to the hardware registers in the Broadcom BCM2835. This clue told me that the wiringPiSetup routine was not being run. This in turn showed me that the global object representing the temperature sensor was being constructed before the WiringPi library was being setup.

The solution to this particular problem was simple enough. I edited the MAX6675 library so that it calls wiringPiSetup directly when initialising. I also set an internal flag if this succeeds. In addition to this I modified the methods to exit with an error if the flag has not been set. This means that none of the MAX6675 library methods should ever call WiringPi functions without the appropriate initialisation having taken place and succeeded beforehand. My code for this example is here. A more general solution might be to add this flag to the WiringPi library itself.

LED Display (MLMC) and Temperature Combined Example

Following my success with the temperature sensor I decided to push the boat out a little further and try to interface to my MLMC LED display system.

The MLMC LED display is a set of LED dot matrix control PCBs I designed to use up some unusual LED modules I had lying about. You can get the full story in this blog post or on the website.

Photo:  Using the WiringPi library to control an LED display and Thermocouple interface

Photo 2: Using the WiringPi library to control an LED display and thermocouple interface

This was a simple demonstration with the RasPi reading from the thermocouple interface and then displaying the temperature on the display. For this example I wrote everything in C. The MLMC interface is very simple and involves clocking 16 bit words of data using two pins, one for data and one for clock. Each word represents a single column on the LED display. This low speed (~5Kbps) synchronous protocol was originally implemented by directly manipulating the digital I/O pins on the Arduino and so was very simple to port to the RasPi with the WiringPi library.

While the ported program functions very well, the waveforms obtained from the RasPi are quite different to those achieved with the Arduino. This is a good example of how the same simple code can be quite different when ported between platforms.

MLMC Clock Waveforms

The function used to send serial data to the MLMC is shown below. This code has a 75µs delay between switching the level of the clock and this gave uniform pulses on both systems. The pulses also appeared consistent from one run to another.

Listing 2: MLMC serial data sending routine


const int spidelay_us =75;

void Send_byte( char data ///< 8 bit data to be sent
			   ) {
    uint8_t temp;	// local copy of the data to be shifted out
    uint8_t i;					
	
    temp = data;	
    for (i=0; i<8; i++) {
		// start the cycle with the clock pin low
        digitalWrite(clockPin, LOW);

		// clock out a single byte
        if (temp & (1<<7)) {
            digitalWrite(dataPin, HIGH);
        } else {
            digitalWrite(dataPin, LOW);
        }
        
		// wait for data bit to be set up
		delayMicroseconds(spidelay_us);
        
		// clock the data out by producing a rising edge
        digitalWrite(clockPin,HIGH); 
		
		// wait for mlmc to read the data bit in 
        delayMicroseconds(spidelay_us);
		
        // shift data along by one
        temp <<= 1;
    }
	
	// leave both pins low when idle 
    digitalWrite(clockPin, LOW);
    digitalWrite(dataPin, LOW);
}

The following scope traces are the result of executing Listing 2 on the Arduino:

Clock pulses from the Arduino to the MLMC modules

Figure 1: Clock pulses from the Arduino to the MLMC modules

Single clock pulse from the Arduino to the MLMC modules

Figure 2: Single clock pulse from the Arduino to the MLMC modules

Arduino has a total pulse time of approximately 80µs for the first clock pulse to MLMC. This extra 5µs I assign to the time taken to call the digitalWrite function, a single shift operation and iterating the for-loop.

The next two traces in figure 3 and figure 4 are produced when running the same code on the RasPi:

Clock pulses from the Raspberry Pi to the MLMC modules

Figure 3: Clock pulses from the Raspberry Pi to the MLMC modules

Single clock pulse from the Raspberry Pi to the MLMC modules

Figure 4: Single clock pulse from the Raspberry Pi to the MLMC modules

You can notice that while the pulses look identical at a quick glance the RasPi has 150µs pulse width; almost double that of the Arduino. I assume that the delayMicroseconds function, which only guarantees that a minimum of the given microseconds have elapsed before returning, is releasing control to the operating system and coming back a lot later than expected. As the delay implementation in the WiringPi library simply calls nanosleep I am surprised this operation takes twice as long. There may be a number of causes for this behaviour:

  • There might be a bug in the way the delay function is implemented.
  • The shift and for-loop iteration might have compiled in a very inefficient way.
  • The operating system simply cannot schedule other tasks quickly enough to return from nanosleep and meet our expectations.

MAX6675 thermocouple interface

This loop was clocking data in from the MAX6675 chip via a “bit-banged” interface. The main loop did not have a delay and was toggling bits as quickly as possible while shifting in the value via a single GPIO pin.

Listing 3: SPI send section from the MAX6675 library


digitalWrite(_CS_pin,LOW); // Enable device

/* Cycle the clock for dummy bit 15 */
digitalWrite(_SCK_pin,HIGH);
digitalWrite(_SCK_pin,LOW);

/* Read bits 14-3 from MAX6675 for the Temp 
 Loop for each bit reading the value and 
 storing the final value in 'temp' 
 */
for (int bit=11; bit>=0; bit--){
	digitalWrite(_SCK_pin,HIGH);  // Set Clock to HIGH
	value += digitalRead(_SO_pin) << bit;  // Read data and add it to our variable
	digitalWrite(_SCK_pin,LOW);  // Set Clock to LOW
}

/* Read the TC Input inp to check for TC Errors */
digitalWrite(_SCK_pin,HIGH); // Set Clock to HIGH
error_tc = digitalRead(_SO_pin); // Read data

digitalWrite(_SCK_pin,LOW);  // Set Clock to LOW
digitalWrite(_CS_pin, HIGH); // Disable Device

The following traces in figure 5 and figure 6 show the results on the Arduino.

Clock pulses from the Arduino to the MAX6675 modules

Figure 5: Clock pulses from the Arduino to the MAX6675

Single clock pulse from the Arduino to the MAX6675 modules

Figure 6: Single clock pulse from the Arduino to the MAX6675

On the Arduino this code gave a uniform pulse train with the pulse widths measuring approximately 6-7µs. As the Arduino is running at 16Mhz I would like to think this could be optimised a lot more to get something like 120ns if I used some assembly or bypassed the Wiring/Arduino API, but that is an exercise for another blog post. 🙂

Clock pulses from the Raspberry Pi to the MAX6675 modules

Figure 7: Clock pulses from the Raspberry Pi to the MAX6675

Close-up clock pulses from the Raspberry Pi to the MAX6675 modules

Figure 8: Close-up clock pulses from the Raspberry Pi to the MAX6675

The RasPi on the other hand gave a very non-uniform pulse train. As this is synchronous communication, the clock does not need to be uniform, it dictates when the data line is read. The average pulse in this waveform is only 150ns wide which is approximately 48 times faster than the Arduino. Given that the RasPi clock speed of 700MHz is roughly 44 times faster then the Arduino clock speed of 16MHz, this makes sense.

The RasPi would vary any individual pulse length by up to a factor of two (from observation) but did not seem to be effected by increasing the load (multiple ssh sessions and running an openssl speed test). The RasPi would also continue to run the MLMC scrolling display and reading the temperature sensor without issues while another process was also reading the temperature sensor at the same time (single_temp.cpp from first example above). Even while openssl was doing speed testing (cpu usage at 98-99%) the visible operation of the screen was not effected.

Investigating Further

The long delay and changing pulse widths could be investigated further with a couple of short programs.

I could investigate the long delay further by looking at repeating the test with the system under different loads and noting the effect on the width and consistency of the pulses. To vary the workload on the RasPi I could use a tool like stress.

We could also step through many values while keeping the system load constant. This would give us an idea if their was a minimum overhead experienced by the delay function or if their was some sort of error in the calibration.

I will leave these as an exercise for another day as plenty of work has already been done on this sort thing before, although not specifically on the RasPi.

Conclusions

This was a very quick look into porting code from Arduino to Raspberry Pi. I found that it was not so difficult to port some very simple applications, the majority of the code would simply run unchanged.

While the code may compile and run, the actual operation of the code will always need to be checked carefully for timing issues and other unexpected behaviour when switching hardware and using new library implementations.

As these systems were using synchronous serial communication the exact shape of the waveforms did not actually need to be uniform for the system to work.

On review of the MAX6675 data sheet the timings slighty exceed the stated maximum clock freq of 4.3Mhz. So If I was intending to use this further I would introduce a short delay into the MAX6675 clock routine to ensure it complies with the data sheet.

The MLMC module operates perfectly with the timings achieved but we are operating at half the throughput we expected due to the delay function not operating identically to the same function on the Arduino. While this didn’t cause a problem in this simple test it could easily have done so in a slightly more complicated system.

USB Microscope

Sunday, April 8th, 2012

I have just purchased a Veho USB microscope and am quite pleased with the result. I was hoping to use this as a very cheap replacement for a good binocular microscope. When soldering very fine pitch surface mount devices for prototype or repair a good binocular scope is fantastic for soldering under.

Below is a video test of me upgrading the ATtiny261 to ATtiny861 on my MLMC controller PCB. While the system is reasonably good for soldering it is excellent for inspecting finished the finished work.

Microscope Video Test at 22x magnification

I took a couple of test pictures using the windows software (Microcapture). These are shown below. The software lets you draw in measurements based on the magnification which is entered manually. It’s not the greatest but it is nice and functional.

Microscope Photo Test at 22x magnification

This shows the mm scale on my steel ruler.

Microscope Test at 400x Magnification

Microscope Photo Test at 400x Magnification

This shows the 0.5mm scale elsewhere on the same ruler.

High Resolution Photo Test at 20x magnification

High Resolution Photo Test at 20x magnification

I have tested the device on Windows XP, MacOS 10.7, Fedora15. On linux I had a few issues that later turned out to be a faulty USB hub. In playing around to get the scope to work on Linux I discovered the great GTK+ UVC Viewer program. As all three operating systems have “USB Video Class” drivers everything worked out of the box (hub issues aside).

If Linux does give you any grief you may need to do a modprobe uvcvideo. I didn’t need to do this as I have another webcam plugged in as well that uses the same driver.

I’m not sure what tricks the windows driver uses to get the higher resolution as these modes did not seem to work on other platforms. If anyone knows how to get the high resolution modes working on Linux I would love to hear from you.

A few website issues but everything is OK now.

Monday, November 1st, 2010

Sorry to all of you who have been having problems with the site this past week. Someone managed to get some malicious code into the site either via a PHP exploit or sniffing my FTP password.

I have managed to get everything cleaned up, reviewed my security practices (no more FTP) and updated my WordPress installation. If you find any images are missing or something on the site isn’t as it was then please let me know.

Apologies to anyone how has been infected by malware. The site was apparently spreading malware to unprotected machines between the dates 19th and 27th of October.

Back in the UK

Saturday, April 24th, 2010

Just got back to the UK after a volcano related extension to my holiday in NZ. I’ve also fixed the EAGLE files link for the Arduino MP3 player shield mentioned in this earlier blog post

STL to IGS (IGES) Conversion

Sunday, December 6th, 2009

I’ve been trying to get my models from Sketchup into a decent file format for use with different analysis engines and for producing drawings for machining.

After a week of playing about with different options I have managed to get from Sketchup files to IGES files.
I used BRL-CAD to convert from .stl to its native format and then exported as an .igs from there.
Below is a copy of the script i used to convert a whole directory of files.


#!/bin/bash
# Convert an STL file to IGES format using BRL CAD

for file in *.stl
do
# Add the -b option or binary format stl files (aoi,solid edge etc)
# stl-g -b ${file} ${file}.g

# Use ascii format for exports from sketchup
stl-g ${file} ${file}.g
done

for file in *.g
do
mkdir ${file}.d
g-iges -m -o ${file}.d ${file} all
cp ${file}.d/*.igs ${file}.igs
rm -rf ${file}.d
done

I did run into an issue or two along the way. When initially export as iges with the command g-iges -o file.igs file.g all the file produced caused every program I tried to load it with to crash with the exception of BRL-CAD which loaded it just fine. I found that when I used the -m option and export all regions to a directory of iges files the files worked. The STL files produced by the STL output plug-in for sketchup produces STL files in the ASCII format some programs may produce files in binary format, in which case you will need to add the -b option to the stl-g command. I had to use this when converting the STL files from the reprap project to iges files.

Why IGES files? Because I couldnt get STEP files. While STL files are widely supported they are mesh files that describe surfaces only. Most professional mechanical CAD packages use constructive solid geometry (CSG) techniques and don’t like mesh files so much. That’s not to say I couldn’t load STL files into these packages but the loaded part was less useful when imported from STL as compared to IGES. An IGES file allows me to measure and convert to a solid object or more easily produce drawings for a machinist to work with.

Complete 3D Model of Butterfly MP3

Sunday, November 22nd, 2009



I hope to use this data to do some stress analysis of the case design using CAE Linux and look at geting the case built using SLA or SLS techniques.

The Sketchup model is at http://www.brokentoaster.com/butterflymp3/photos/ButterflyMP3_and_Cases.skp

3D Model AVR Butterfly

Saturday, November 14th, 2009

I’ve been playing with Google SketchUp for a while as a free tool for doing electronics enclosure design (ie. MP3 Player cases). It seems quite capable although not really targeted at designs in the mm range. I think I will use a larger scale like 10:1 or 100:1 next time to see if that makes things easier.

Here is my first attempt at an AVR Butterfly model for use in case designs on the data logger and MP3 player. You can download in skp and stl format. To export SketchUp files as STL I have used the plugin from http://www.guitar-list.com/download-software/convert-sketchup-skp-files-dxf-or-stl

Stereo Lithography (STL)
SketchUp (SKP)
Image (PNG)

Battery Capacity Logger

Wednesday, November 11th, 2009

I just replaced the battery in the 2005 ibook G4 today, great to return to the days of 4 hours of use. I decided I’d like to monitor the life of the battery and so wrote a quick cron job script to log the battery capacity every day. I also have installed this on my main laptop which still gives me 3 hours after 18 months of use.

Write the script.
#!/bin/sh
# batterylogger.sh : Log battery capacity to a file
#
date >> ~/batteryCapacityLog.log
system_profiler SPPowerDataType | grep “charge capacity” >> ~/batteryCapacityLog.log

Make it executable and put somewhere sensible.
chmod 755 batterylogger.sh
cp batterylogger.sh /usr/local/bin/
Make sure it is activated daily by adding the following line in crontab using crontab -e which will make it run at 5:10am every day. This time is chosen to not clash with other actions executing should my laptop be awake at 5am and also to ensure it run each morning when I wake the laptop up.

10 5 * * * /usr/local/bin/batterylogger.sh

The format looks like the following:
Wed Nov 11 20:03:26 GMT 2009
Full charge capacity (mAh): 4859
I may improve the format in the future and add some nice “gnuplot” plots but this gives me the info I want right now. For the record, the outgoing battery was showing a capacity of around 350mAh. This translates to roughly 10-15 mins of use. OS X 10.5.8

The MLMC website is up.

Sunday, October 4th, 2009

I’ve just put a new website up for the MLMC project. No new information over what has been mentioned in the previous blog post, but it is a start. With the initial page up I hope it will encourage me to publish information sooner rather than later. Of course I still need to find time to do some actual work on the project. Next week perhaps…. You can find the site at http://brokentoaster.com/mlmc/

Modular LED Matrix Controller (MLMC)

Friday, September 18th, 2009


What is it?
The MLMC is a smart daisy chain-able LED matrix module.
I call it smart because a display of these can be extended without changing either the firmware on the module controller or the firmware on the display controller. Each individual module will take care of refreshing its display. When new data is sent old data is passed along the chain to the next module. This makes building an arbitrary length scrolling display very simple to implement.

The LED matrix is on a separate PCB so it is simple to adapt to other LED matrices without chaining the controller PCB/firmware. This means that if you were producing a number of different sized displays you could use the same controller PCB. For example for one made from a 16 by 16 LED matrices or a large one made from custom PCBs using 16 by 16 individual 10mm LEDs.
Why?
I liked all of the many LED matrix projects seen on the web and in Circuit Cellar magazine. To enlarge or adapt these displays would mean a redesign of firmware and hardware.

I had a small number of dense 16 by 16 matrices sitting about from my times bargain hunting in Akihabara. These are unused by any of the projects I have seen on the web and in magazines. These matrices have a strange footprint, the pin layout is a cross formation rather than two parallel rows of pins which is more commonly seen). This means work is needed to adapt existing projects to work.

If I built a system purely around the LED matrices I have then very few people could use the resulting design. I would also not be able to reuse the design once my limited supply of these matrices was consumed. By separating out the control hardware from the display hardware I am able to make a much more flexible and enduring design.

I’ve always been a fan of the 2 Line LCD displays which are common in many projects. These have a standard well known interface so it is trivial to add one to a project. I want to bring that ease of implementation to scrolling LED matrix displays as I have many projects that could all benefit from a large display.
What has been done so far?
A prototype 2 Layer PCB has been manufactured by Batch PCB.
Some basic screen display firmware has been written.
A system tested with 1 Bit per pixel, 16 bit columns of the display are clocked in and displayed while last word in buffer is clocked out.
Preliminary PWM brightness control has been tested but not on a pixel per pixel basis.
What needs to be done?

Hardware
  • Move resistors ( LED module pcb)
  • Add decoupling caps (control module pcb)
  • Add local voltage regs (control module pcb)
  • Build more modules for testing of chaining
  • Build different LED Modules
Firmware
  • Extend from on/off pixels to brightness value
  • ISR response needs improving
Software Library/Examples
  • Arduino software is only a basic testing routine.

What will be done?
To call this project finished these are the things I hope to have done.
  • Release all firmware under a Creative commons License.
  • Release all pcb files under a Creative commons License.
  • Release protocols /data sheets under a Creative commons License.
  • Release an Arduino library to talk to a string of these under a Creative commons License.
How Long will it take?
It will probably never be completed. So I hope to publish unfinished work when it is suitably unfinished whenever I remember.