Skip navigation

Raspberry Pi Projects

11 Posts authored by: shabaz Top Member

Introduction

This blog post is about powering a new security camera (HAL-CAM 9001) using network cables. These could be cables already installed in an office or home environment, saving costs, or they could be new cables installed indoors or outdoors (using weather resistant cable).

 

This sub-project is part of the HAL-CAM 9001 project but it is generic enough to suit other scenarios too. It could be used to power a Raspberry Pi remotely for other tasks. Other single board computers (SBCs) can benefit from this project too.

 

HAL-CAM 9001 doesn’t have a lot of free space inside so this project was made to be ultra-compact; 2cm high and 6x5cm footprint. This project supplies 5V at up to 2.5A.

The schematic and PCB files are attached, ready to be sent to a board manufacturer.

poe-annotated.jpg

 

What is PoE?

Power over Ethernet is one of these technologies that when you use it, you find you really need it. Over the years it has saved costs, copper, and provided a reliable and safe solution to providing energy to many diverse devices over Ethernet based local area network (LAN) connections.

 

At its debut, it was said that standards-compliant PoE was effectively one of the few worldwide standards for power so one could take a device and be assured it would work anywhere in the world, in contrast with the mains supply voltages and plug shapes which vary from country to country. And it doesn’t require an electrician to install!

 

Part of the safety of PoE comes from the ability to automatically and electronically control the delivery of power. By default, the network connection has no substantial power capability enabled and is finger-safe. When the connected device requests power the far end will switch on the supply. Note: the equipment that can supply power is known as the Power Sourcing Equipment (PSE), and the device to be powered is the Powered Device (PD).

 

With the earlier standard (IEEE 802.3af) the request was as simple as having a 25k resistor across a couple of pins. If the resistor was present, then the far end would turn on the power. This solution provided about 13W of power to the PD. The later standard IEEE 802.3at nearly doubled this capability, to just over 25W of power. This later standard had a more complicated method of enabling power; the PD would provide a varying load over time in a special combination that would allow the PSE to detect that the PD was an 802.3at capable device and then supply up to one of four particular levels of power. Once this was achieved it was possible to signal information in Ethernet packets to further refine the power requirements.

 

Today Universal PoE (UPOE) has more than doubled the power capability to 60W – equivalent to an incandescent light bulb!

cam-project-overview.png

 

This project provides IEEE 802.3af and 802.3at standards based power capability. The output is at 5V, capable of up to 2.5A (i.e. up to 12.5W). This level of output is ideal for remotely powering HAL-CAM 9001, or other Raspberry Pi projects, BeagleBone Black (BBB) or other single board computers (SBCs).

poe-bbb-annotated.jpg

 

Note that the powered device doesn’t actually need to have an Ethernet connection at all. It is possible to use PoE to charge your mobile phone.

poe-phone-charge.jpg

 

How do I get PoE?

Assuming standards-based PoE is required then the best way is to pick up a switch with 802.3af or 802.3at capability. In the UK for consumer use the 802.3af compliant 8-port TP-LINK TL-SG1008P costs about £50 from Amazon and provides 4 devices with up to 13W of power each, simultaneously (I have not tried this switch so it isn’t a recommendation, just a pointer to what is out there).

 

There are also so-called ‘PoE Injector’ adapters, also misleadingly called 2-port PoE switches sometimes. These are not great because often they are not IEEE 802.3af or 802.3at compliant and may supply power all the time; they are therefore not very green because their power cannot be shut down electronically. A true standards compliant PoE capable switch is the far better choice and doesn’t cost much as mentioned earlier, considering it can power up to four devices.

 

At the device end, it needs to support the same standard. If the device doesn’t support PoE then an off-the-shelf external PoE adapter can be used; it is standards compliant and taps off the supply to be used to power the device.

 

Building It

poe-maxrefdes.jpg

The schematic is shown below; it is really simple because most of the functionality is contained in Maxim’s MAXREFDES98MAXREFDES98 board which contains a DC-DC converter and the circuitry to handle the standards negotiation. The rest of the board mainly consists of the Ethernet transformers and connectors. Note that it would be wise to add some suppression circuitry as detailed in the original HAL-CAM blog page; I forgot to add it to this revision 1 PCB but the same method (TVS diodes) can be used as in the original blog post. At some stage I will update this blog post with revision 2 files which will correct this omission.

poe-schematic.png

 

To construct this project, solder up the smallest parts first (the resistors and capacitors), ending with the largest parts. The fuse is optionally available in a socket which will fit the board but I chose to save some cost and directly solder the fuse.

 

Network cables are available in short lengths but I wanted an extremely short length (a few cm) for fitting inside HAL-CAM 9001 so I used an RJ45 tool to do that. The back of the PCB has a reference indicating which color wire goes where.

poe-complete-underside.jpg

 

Testing It

There is not much chance of error during assembly since there are so few parts in this project (the part values are in the schematic but a list of components will be published in the next few days). I connected this project via the longest length of network cable that I had (5m long) to a switch, enabled PoE on it (some switches require configuration for this) and then used a multimeter to confirm 5V was present on the output supply connector. The on-board LED was lit too, confirming that the board was receiving power. The multimeter confirmed the correct output so I proceeded to plug it into the Pi and verified that the Ethernet link came up and I had network connectivity. I can now issue a shutdown command to the Pi remotely using SSH, and then configure the switch to disable power. Whenever I want to turn the Pi on, I can configure the switch to turn on the PoE capability.

 

There are additional tests that should be done (such as confirm the voltage output under changing loads, verify the ‘eye diagram’ for the signals over the network cable, check for RF interference and checking throughput to see if there are any packet errors occurring). These will be done later at some stage; for now the board is functioning well enough to continue HAL-CAM 9001 development.

 

Summary

PoE is easy to use and it can be useful to be able to retro-fit non-PoE devices with the capability. The Maxim module makes this really easy. The PCB files are attached ready to send to a manufacturer. Note that the PCB also has some additional “features” (see photo below) which can be hack-sawed off and put aside for now (they are for unrelated mini-projects which will be documented at some later stage; feel free to guess what they are! It is not too difficult).

poe-extras.jpg

 

See also:

 

HAL-CAM 9001 – Building a New Security Camera

A Linux Based Image Detecting Security Camera

Traditional security camera solutions are very good at detecting movement however these solutions are unaware about what that movement actually is. They cannot automatically tell the difference between trees moving in the air, or a car or a human.

We wanted to have a system that could identify humans and record such information; this would allow it to discriminate between uninteresting activity (such as a car driving past a road) and more interesting activity such as the presence of a stranger. Thus the HAL-CAM 9001 was born.

The camera doesn’t just output a video file; it also outputs a text file or table that contains time-stamps to indicate exactly when a human was spotted. Others may wish to identify other things such as (say) a cat. The idea is to have a searchable and readable text file that a user can quickly browse for any interesting activity.

hal-cam-photo.png

 

This tutorial describes the build process. This part covers the hardware in order to have an outdoor-ready HAL-CAM 9001.

Check out the 90-second video summary (it is followed by a few minutes of video showing some of the construction that we recorded).

 

What is this project about?

The UK has always had a tradition of embracing the security camera. When I went to college I remember my apartment still having a black-and-white video entry system containing an image tube such as a Vidicon. This was despite the Charge Coupled Device (CCD) having been invented several decades previously; testament to how rugged and reliable valve and tube technologies could be.

 

Fast-forward to 2016 and there are millions of security cameras scrutinizing the public and a typical conversation during a coffee break with a colleague could well begin with “so what security cameras do you have?”; It was just this type of conversation that led to my colleague Aminder and me discussing the latest in home IP camera technology (IP cameras use a network to transfer video data) and how he was using a Raspberry Pi to operate it. We wanted to build our own low-cost open source IP security camera solution suitable for outdoor use.

 

aminder-shabaz.png

HALCam: A joint project by Shabaz and Aminder

 

The higher performance Raspberry Pi 3 offered some interesting possibilities because it means we can run software that ordinarily needed more computing power than was possible in a low-cost outdoor unit. The Linux operating system and open source projects allow for features to be implemented that today are not present in typical home cameras, in particular the image recognition feature.

 

We think such a system is potentially more useful than a traditional camera because there is no need to perform a video search; it is easier to just hit Ctrl-F and search for text in a file.

 

Also the more we thought about it, the more we realized that what we actually wanted was a general purpose outdoor computer that could be used for other functions too. For instance if the camera is outdoors then it may as well do things like measure the outdoor temperature, or in the future open electric gates, switch on the lighting when people arrive and so on. The Pi 3 does have several built-in wireless technologies that could be useful for this.

 

Basic Tools

The main aim of the hardware design is have an outdoor-capable weather-resistant camera/computer. To build it we used a weatherproof plastic case and fitted everything using nuts/bolts and using acrylic or Perspex sheet as our support material inside the case to hold everything in place. The design could be replicated exactly or with modifications to suit the materials and equipment that is available. For example a 3D printer could be used instead of cutting acrylic parts.

In general some basic parts and tools that will come in handy are listed below.

 

  • M3 (3mm) screws short and long
  • 3mm thick acrylic sheet (around 300x200mm is more than enough)
  • 5-minute 2-part epoxy glue (such as Araldite Rapid)
  • Cutting tools, clamps
  • Electric drill and drill stand (if possible), soldering iron
  • Eyewear because lots of drilling and cutting is involved

 

 

Construction Overview

In essence HAL-9001 consists of a computer (the Pi 3Pi 3), the camera modulecamera module and a power supply. There are therefore three main steps to building HAL-9001;

 

  • Building a Pi Subassembly
  • Building a Camera Subassembly
  • Building a Power Supply Board

 

There are also miscellaneous operations that need to be performed to fit and connect everything into the enclosureenclosure, such as drilling holes, fitting the heat sinkheat sink and cable glandcable gland, attaching wires and so on. These operations are varied and will be discussed throughout this tutorial. Finally there are some cosmetic operations that are optional such as painting the enclosure.

 

Refer to the diagram here for the terminology that will be used in this project.

exploded-diag.png

 

Building the Pi Subassembly

The Pi Subassembly consists of a Pi 3 attached to an acrylic (Perspex) sheet called the Pi Mount using plastic spacers and a shaped heat pipeheat pipe in-between. The photo here shows it upside-down. When placed inside the case, only the underside of this will be visible.

pi-subassembly-upside-down-var1.jpg

 

The Pi Mount piece of acrylic is used to secure the Pi into the case using two screw holes. It also serves another purpose; it acts as a support for a heat pipe. A heat pipe is a sealed metal tube which has channels inside that pass thermal energy using a fluid. It is needed because the Pi can get hot when running intensive software. This is particularly the case when ARM ‘NEON’ computer instructions are executed repeatedly, and this is the case for one of the software libraries which is needed for this project. It is essential to keep the Pi cool inside the enclosure. Our strategy was to rely on passive air-cooling using a heat pipe and a heat sink but if you’re in a hot country this might not be enough and you may need to also consider installing a small fan.

heat-pipe-asus-example.jpg

(Picture source: Asus)

 

Heat pipes are often seen inside PCs and the technology helps this particular project in two ways;

 

  • It enables the heat sink to be placed at some distance on the outside of the enclosure
  • It aids in serviceability because it is possible to use a screw and clamp arrangement to attach the heat pipe against the heat sink and be able to easily unscrew it whenever the Pi Subassembly needs work; something we could not easily do if the heat sink was directly attached to the Pi

 

In summary the heat pipe simplifies the design and eliminates the need for fans because we can use a large external heat sink.

 

Cut a sheet of acrylic (or make something appropriate with a 3D printer for example) such that it can be mounted 20mm above the surface of the Pi’s printed circuit board (PCB). This height is achieved by double-stacking 10mm spacers in-between.

 

A slot is needed for the camera flat flex cable (the earlier photo shows the flex cable in-between the Pi Mount and the Pi, but that was an experiment and it was later determined that it was easier to run the flat flex on the outside). We also made a cut-out where the 40-way Pi GPIO header pins are for slightly easier access.

pi-plate.jpg

 

All spacers and screws were plastic instead of metal; this is especially important for the lower-rightmost corner in the photo above because the Pi’s antenna is located just a few millimeters away on the PCB. Metal screws and spacers so close to the antenna will affect the communication range.

The Pi’s mount holes are less than 3mm in diameter which is awkward; it is a lot harder to find 2mm or 2.5mm spacers than 3mm ones. If it is not possible to purchase (or perhaps fabricate) appropriate spacers then an option is to do what we did; drill out the Pi’s holes to 3.2mm (this will invalidate the warranty). We used a hand-held powered drill but doing it by twisting the drill bit by hand unpowered might be less risky.

drill.jpg

 

As mentioned two 10mm spacers were combined to provide 20mm height. The lower one was a press-fit spacerpress-fit spacer. The upper spacerspacer comes threaded, and we didn’t need the thread so it was drilled out with a 3.2mm bit.

 

The heat pipe needs bending into a suitable shape. The easiest way is to create a jig (guide) by drilling some holes in a scrap piece of wood or plastic and then push some pegs (or cut up metal rod) into the holes.

heat-pipe-bending-operation.jpg

 

One end of the heat pipe will be glued onto the Pi’s microprocessor chip and the other end will eventually be clamped onto the heat sink.

heat-pipe-described.png

 

To glue the heat pipe onto the Pi we used a thermally conductive adhesivethermally conductive adhesive. It is very strong. Clean the surfaces with isopropyl alcohol (IPA) and mix up the adhesive (it comes in two parts). Wood barbeque skewers are handy glue mixing sticks/applicators. The photo shows enough glue mixed for a dozen heat pipes so there was a lot of waste. Make sure the mix ratio is approximately correct (this was the reason for the waste; it is easier to be more accurate when mixing a larger amount) because if the ratio is incorrect or it is not thoroughly mixed then the glue will not fully harden. After the glue has been applied clamp it gently (use some rubber insulating material on the underside of the Pi to cushion the clamp). The glue takes 48 hours to dry but this can be reduced to just a few hours by turning on the Pi and installing and running the cpuburn-a53 program which will nicely heat up the chip.

heat-pipe-gluing-collection-annotated-r.jpg

 

Power off then loosely assemble everything together to confirm the heat pipe is still bent correctly. If some slight adjustment is needed hold the glued end and gently bend the rest of it.

 

Next loosely assemble the Pi Mount acrylic plate and mark off with a pen where it touches the heat pipe. Remove the Pi Mount and apply heat resistant glue (we used UHU Max Repair) and then fully screw the Pi Mount plate onto the Pi. The end result is a permanent Pi Subassembly that can be easily connected to a heat sink and is removable as an entire unit.

uhu-application-collection.jpg

 

If the Pi ever needed replacing then the heat pipe would have to be torn off the acrylic plate and another heat pipe would need to be used. Fortunately they are low cost.

 

At this stage some case preparations can be performed to figure out how everything will fit inside the desired case. We used an IP65 rated box from MulticompIP65 rated box from Multicomp (the IP65 rating was lost through drilling some holes for this project! but everything can be sealed back up).

 

The case we used had some plastic stand-offs moulded into the inside base, and these need to be removed (for example with a Dremel tool) to get the base approximately flat.

 

The acrylic Pi Mount has two holes for securing it to the case however we wanted to minimize any holes to keep weather-proofing steps to a minimum. The solution we used was to create a small Threaded Plate, which was a strip of 3mm thick acrylic with metal screw thread inserts fitted.

pi-subassembly-case-operations-collection.jpg

 

The metal screw thread inserts are intended for injection moulded parts. To fit it into the acrylic sheet just drill a hole slightly smaller than the insert (we drilled to 3.5mm) and then set your soldering iron temperature to 180 degrees C and put the insert onto the soldering iron bit and gently push it into the acrylic. It will slowly melt its way in. When it is entirely embedded in the plastic just lightly pull to remove the iron, leaving the insert inside the plastic. It will cool rapidly and remain tightly embedded. Then the Threaded Plate can be glued inside the case at a suitable position; leave space on the HDMI connector side of the Pi, because this is where a USB-connected mSATA solid state drive (SSD) needs to fit later on.

 

Mark out where the heat sink cut-out is needed in the enclosure, by loosely screwing the Pi Subassembly onto the Threaded Plate and marking up with a pen. The rectangular shape can then be cut out.

 

Building the Camera Subassembly

The Camera Subassembly is much easier to construct. The only purpose it serves is to hold the camera in a suitable position.

camera-subassembly-mounted.jpg

 

We used two pieces of acrylic to achieve this. The Camera Mount piece is a friction-fit onto the protruding ends of the spacers that we used. The smaller Camera Adapter piece of acrylic serves to just provide a useful way of holding the camera. The camera has very small holes and generally feels fragile so it was preferable to just permanently attach it (using a foam pad and a tiny bit of epoxy glue at the corners) to the Camera Adapter.

 

To make the adapter we again used the threaded insert method since it worked so well the first time round.

camera-holder.jpg

 

The Camera Mount plate can optionally have a cut-out as shown in the photo. This was to allow the Pi’s circuit board some ‘breathing space’ and prevent it getting too hot. We used countersunk nylon screwscountersunk nylon screws because metal would be too risky so close to the PCB with the mount method that we used. Only one length of nylon screws is needed for any project because if they are too long they can be easily snipped with wire cutters.

 

The camera flat flex cable was routed around the outside of the plates and then taped into position. It needs to be folded as shown in order to translate the position of it from the center down to where the connector actually is.

cam-flex-collection.jpg

 

The end result was a single convenient module consisting of the Pi Subassembly and the Camera Subassembly. It can be fitted and removed at any time from the case.

 

Building the Power Supply Board

The Pi will be performing a lot of computation. The Power Supply Board contains a DC-DC converterDC-DC converter which is responsible for ensuring that the Pi has a stable 5V DC supply at all times regardless of the workload. Ultimately the 5V supply will also be used to power the solid state drive (SSD), the camera and any other device attached to the Pi, so we wanted the Power Supply Board to offer around 15W of power (up to 3A at 5V). The input to the DC-DC converter is taken from the 8-wire network cable which will connect from the home to the camera location. This way just a single cable is needed to connect between home and camera, saving costs and simplifying the deployment.

project-diagram.png

 

Only four wires inside the cable are actually used by the Pi which means that four are available to supply DC power at a voltage suitable for the DC-DC converter input which is any value between 6-14V. We used two wires for the positive and two wires for the negative.

 

This scheme is not an official ‘power over Ethernet’ (PoE) scheme but to correct it a later project (now complete!) will implement standardized PoE to replace this unofficial power over Ethernet scheme which we are using.

schematic-power-supply.png

 

The network cable from the outside world is connected to the Power Supply Board which actually serves two purposes. Firstly it takes the unused wires to power the DC-DC converter and supply a 5V output to the Pi. Secondly it passed through the Ethernet wires on to the Pi, but also suppressessuppresses any spikes on the wires.

 

The current design uses some surface mount devices (SMD) but it was assembled up using stripboard and a couple of SMD adapter boards (SOIC-8SOIC-8 and SOIC-16SOIC-16) and a normal soldering iron (2mm size bit). The SMD parts used are not overly tiny to make it easy to hand-solder. If there is interest we will design an open source PCB for this project.

 

The main components used are:

 

supply-board-bits.jpg

 

Once the board has been assembled it is recommended that some tests are done without the Pi, to check everything is ok. With no power attached use the diode check function on the multi-meter to confirm there are no shorts between any of the RJ45 pins apart from pins 4 and 5 which should be shorted (they are the DC+ pins) and pins 7 and 8 (they are the DC- pins). Also, check there is no short on the 5V output connector or test point and ground. Attach a 12V supply to the board (either directly to the test points, or using the end of a sliced up network cable), ensure it is set to a low current (about 150mA) and power it up while observing the output using a multimeter or oscilloscope. It should be very close to 5.2V. If this all works then it is likely that the board is functioning sufficiently well to proceed!

supply-assembled-with-insert.jpg

 

We ran some tests using resistors to simulate the Pi under different workloads. The board was tested under no load and then a medium load (1.3A) and then a high load (2.9A). The resistors of course run hot! - they were dissipating close to 15W of power.

supply-board-testbed.jpg

 

scope-traces.png

 

Shown in an earlier photograph, we needed to build up a cable to connect the 5V output to the Pi. Usually people have the official Pi power supply attached to the micro USB connector. It is impractical for this project so we directly connected the 5V supply to the pins on the 40-way connector instead for a more simplified approach.

gpio-pinout.png

 

There are more than one ground pins on the 40-way connector, and there are two 5V pins. We doubled-up the wires so that both 5V pins and the two ground pins were connected to the Power Supply board. Network cable is great and low cost; we just used pairs of wire from a cut-up cat 5 network cable lying around. We also used a decent socket connectorsocket connector (i.e. not from ebay!) to try to ensure good long term contact with the pins on the 40-way connector. If you can find one, an adapter board could be used. Otherwise it is possible to directly solder to the socket connector.

pwr-cable-gpio-end-collection.jpg

 

At the Power Supply board end we used a Molex Ultra-Fit connector socketMolex Ultra-Fit connector socketplugplug and crimp pinscrimp pins; it is the ideal size for either soldering on wires or using a low-cost crimp toollow-cost crimp tool.

pwr-cable-molex-end-collection.jpg

 

Case Operations

We needed to do a few last things to make the case ready for this project. A hole was cut and an adapter ring called ‘Universal Filter Adapter for GoPro Hero HD 3’ was purchased from Amazon to fit it. The hole was made by drilling lots of small holes and then filing out into a larger circle.

cam-window.jpg

 

(The case was sprayed white just for preference). Next, glue the adapter ring so that the seal is water-tight.

 

The heat sink had holes tapped in it. If you don’t have the tools for this, nuts and bolts could be used. Either way, some sealant will be needed on the other side if the hole goes all the way through (we tried to keep it a partial hole, but it was not feasible with the particular heat sink that we had). The heat sink is either glued to the case, or another couple of tapped holes can be used. The cable gland can be inserted and sealed too.

heat-sink-details-collection.jpg

 

A network cable can now be connected. It doesn’t have to be too long because it can always be extended using back-to-back RJ45 socket adapters and then the junction can be sealed. After passing it through the cable gland, the cable needs the RJ45 plugRJ45 plug to be attached.

network-cable-assembly-collection.jpg

 

The Power Supply Board was fitted inside the case using a grooved piece of acrylic and a threaded spacer. The acrylic has a groove or notch cut into (or glue thinner pieces of acrylic into this shape) for the stripboard to fit in. A spacer is glued to the base of the enclosure so that the Power Supply Board can be secured with a single screw after it is pushed into the notch.

pwr-module-securing-collection.jpg

 

The photo below shows the insides of the completed project. Note that the solid state disk (SSD) will most likely require a ferriteferrite placed around the USB cable. This is because of electromagnetic interference (EMI) susceptibility causing the wireless signal to suffer which will cause packet loss or delay if the WiFi is enabled on the Pi. The ferrite core helps a lot although it might not completely eliminate the issue. Another option is to not install an SSD.

cam-internals-all.jpg

 

A ‘37mm UV(C) Digital HMC Screw-in Filter’ from Amazon was screwed onto the adapter ring. To become watertight an O-ring is needed sandwiched between the glass of the filter and the adapter ring. A '33mm x 25mm x 4mm' sized O-ring should fit, but ours had not arrived in time to physically confirm this [Edit: it arrived, and it fits well. When fully screwed, the O-ring is compressed by around 0.5-1mm, this is a guess based on visually seeing the O-ring pressed against the glass].

 

Trying it out

While we were finishing the design, spannerspencer suggested we adopt the red HAL eye in the final design : ) We drilled out a hole in a piece of circular plastic (it was a lens intended for an LED although we drilled out all of it and were left with just the rim), sanded it to become translucent and then glued an LED to it (we sanded flat part of the LED too, to make it easier to attach). It was tacked lightly around the camera module and directly connected to an I/O pin with a 100 ohm resistor in series.

 

It worked really well. From a distance it does look like HAL’s eye, and the center hole is barely visible, it is an eye pupil anyway!

 

It serves a great practical purpose. During power-up or in fault conditions it can be made to flash in different sequences to indicate different conditions. In normal use it would be switched off, but interestingly even switched on it had only a slight impact to the video image; very little is reflected off the glass.

 

More tests need to be done but we did run a brief performance test. With the case entirely closed up and the unit placed vertically as it would be deployed, the ‘cpuburn-a53’ program was run. This was at 25 degrees C ambient, indoors (i.e. no breeze). After several hours the CPU had not dropped its speed, and the temperature reported by it was hovering around the 76 degrees C mark. The external heat sink was hot! With hindsight we would go for an even larger heat sink. With such a weather resistant design HAL-CAM 9001 could even be externally water-cooled.

 

Summary

By adopting the heat pipe and a modular sub-assembly construction style it was possible to create a design that can be easily serviceable and should be weather resistant. We hope that people adopt parts of the design and improve on it and share their ideas, in order to have a useful outdoor image processing system. We only got as far as we did thanks to the excellent support from Farnell and Element14 who provided the hardware and valuable advice and ideas throughout.

 

See also:

HAL-CAM 9001 - Building a Power over Ethernet (PoE) Supply

 

Note: This is part 1 of a 2-part post. For part 2, click here: Raspberry Pi 3 Dynamic Current Consumption, Power and Temperature Tests

To see an implementation using a heat pipe, see the Outdoor Pi 3 Image Recognition Security Camera project (aka HAL-CAM 9001)

rpi3-22mm-annotated.jpg

Inspired by Christopher's cstanton  Raspberry Pi Operating Temperature report (with thermal photos from Gareth Halfacree) regarding the heat dissipated by the Broadcom chip on the Raspberry Pi 3, and the discussion with bwelsby we started searching around for ways to keep the Pi cool.

Ceramic heat sinks have an innovative structure (vias or micro-pores) which allow a heightened thermal conductivity compared to traditional aluminium heat sinks. They also can have the advantage that they won't affect radio frequency (RF) communications as much, when positioned close to the wireless antenna that is present on the Pi 3.

Furthermore, ceramic heat sinks are not electrically conductive and therefore there is no risk of accidentally shorting something on the Pi.

Back-of-the-envelope calculations (we don't have all parameters since we don't have a copy of the Broadcom datasheet to examine the device operating conditions in detail, nor a copy of the schematic to examine if we can measure device power consumption isolated from the remainder circuitry) suggests that a heat sink with thermal resistance of around 10 degrees C/W might be effective to keep the Broadcom chip's internal temperature below 120 degrees C when the ambient temperature is below around 40 degrees C. These are guesstimates until practical measurements have been taken.

heatsink-guesstimate.png

Armed with this information, I searched for a suitable sized heat sink and I found a cheap aluminium one. However bwelsby and cstanton suggested that there may be issues with the heatsink getting in the way of connected HAT boards on top of the Pi, and Brian suggested examining ceramic heatsinks.

In summary, I think these parts may be suitable although measurements still need to be done:

22x22x2.5mm MPC222225T22x22x2.5mm MPC222225T

15x15x2.5mm MPC151525T15x15x2.5mm MPC151525T

(Optional) 20x20x10mm 5V DC fan MC33873(Optional) 20x20x10mm 5V DC fan MC33873

(EDIT: after some discussions below, it looks like this Sunon 'DR-MagLev' design fanSunon 'DR-MagLev' design fan is a far better choice, it is 25x25x10mm, quieter, higher throughput, and more efficient with overall lower power consumption. There is also a 25x25mm finger guard25x25mm finger guard).

 

The Broadcom chip is about 14x14mm in size, and ceramic heat sinks do exist in approximately that size. However it is possible to attach a larger heat sink if desired.

The photo below shows the parts that were examined. All of these ceramic heat sinks come with adhesive tape on the underside; the protective tape is removed and the heat sink will stick to the top of the integrated circuit.

The photo at the top of the blog post shows the largest 22x22mm ceramic heatsink.

rpi3-heatsink-ideas-annotated-w.jpg

The photo below shows a heat sink closer to the size of the Broadcom chip, 15x15mm. It also shows a 10x10mm heat sink on top of the USB hub/Ethernet controller chip, however this is really not needed. It doesn't get very hot according to the thermal photos in the previous blog post.

rpi3-15mm-10mm-annotated.jpg

The memory chip on the underside gets hot too. If desired, the 15x15mm heat sink could  be attached there too. The 22x22mm one is too large for that location due to nearby components (the memory chip has a lower height than the Broadcom chip on the top side).

rpi3-underside-view.jpg

So, I plan to attach a 22x22mm part to the Broadcom chip on the top of the board, and possibly a 15x15mm heat sink to the memory chip on the underside. I don't think a fan will be needed unless a very small enclosure with no natural ventilation was used, or if the Pi was in a very warm environment.

In that case, a fan may be an option. I tried the MC33873 fanMC33873 fan and it generates a usable level of air that can be felt from a distance of 10cm or more. However it does generate a small amount of noise too (possibly inaudible if the Pi will be behind other items such as a TV, but I think there is still a risk it could be audible. The voltage could be reduced from 5V to lessen the noise). It could be mounted on the heat sink as shown here although I think a small gap would be good to allow forced air to hit the entire top face of the heat sink. (The red dot on the fan was placed by me so that I could see it spinning). The fan could be secured with epoxy adhesive. The overall height is less than the height of the USB connectors on the Pi 3. The problem with this is that a HAT board cannot be plugged on top if there is a fan in the way.

rpi3-top-fan-crop.jpg

A very nice solution would have been to put the fan on the side (to the left side of the photo above) so that the fan could blast air across the entire top face, and the underside of the board. However the display connector (the long white thing on the edge of the board in the photo above) is in the way and would block the flow of air which is extremely unfortunate. The Pi 3 wasn't designed with air flow in mind : ( However it might be possible with some 3D-printed duct design to achieve something that could work.

 

To summarize, some heat sinking ideas have been suggested however it is for further examination to see how well they perform. It will be good to see what solutions people come up with over time.

Note: This is part 1 of a 2-part series on an experimental user interface

Part 1: - You are here! <---

Part 2: - Not yet written! Bookmark to be notified here when it is available

 

Note: The technique described here is experimental and should be restricted to the sole purpose of UI implementation, and the browser files should be local. Security considerations beyond the scope of this blog post would need to be taken into account if the pages accessed by this technique were remote and accessed via a network.

 

Introduction

This blog post is about a user interface based on web technologies including HTML.

 

It enables the use of typical hardware (such as buttons, LED displays, TFT LCD displays and so on) for the user interface, but with all software control (including display information, text, graphics, styles and user interface response behaviour) implemented in HTML and any other desired web technologies such as JavaScript.

 

The aim is that the same code can be used to build very different looking user interfaces. Furthermore the same code could also be used to provide remote management from a browser. The views can be displayed differently to suit the hardware. With a large screen TFT LCD the user’s experience will be different to a (say) 16-character single-line display, but both should be possible with the same code.

 

An Example – Home Lighting Controller

Just as an example, a low-cost home lighting controller with constrained user interface hardware may have just push-buttons to switch on/off lights in different rooms of the house, and LEDs (one LED per room) to indicate which rooms are switched on.

html-ui-lighting-controller-example2.jpg

 

A more advanced (and expensive) home lighting controller with a TFT LCD and touch-screen may display a plan view of the home with rich graphics, a slider to select the floor of the home, and allow users to touch the desired room and show in a colored graphical image if lights are switched on or off.

 

If network connectivity exists then a web browser-based interface for the lighting controller may implement security including a password, and have a mode with simpler graphics and text so that it can be used from a smart phone.

 

The desire is to allow all of these methods of control to be possible (in a single way) for a scalable experience to suit the hardware that exists. It basically extends the usual web browser techniques to work with diverse input/output devices.

 

Why do this with HTML?

HTML is great for providing information; scripts or programs (along with HTTP) provide the interactivity. In the times when graphics were not always possible simple text-only browsers like Lynx existed to provide access to HTML content. The HTML file was rendered in text-only, and any graphics were ignored. The precedent therefore already exists for HTML on constrained displays (there are also plenty of Internet of Things projects today that extract HTML content and send it to an LCD character display on wireless nodes but they often use functions such as string extraction for extremely basic HTML parsing with no scalable experience and the interaction is basic).

 

HTML and associated technologies such as CSS and JavaScript are attractive because they are fundamental to all web pages and therefore there is a possibility that programmers will have encountered them to some degree. No need to learn Python and other languages or technologies if you don’t want to. It also means that debugging can be simple; just run the code in a browser! There is no need to have access to the physical hardware until you are ready for it. In a team, it simplifies allowing some people to work on physical hardware while others work on low-level interfacing in software and others can work on the user interface logic and application logic.

 

And to be honest another reason to do this was partly curiosity: how feasible is it to build an interface using HTML and associated web technologies for a device with constrained input/output for the user interface, and could it be responsive?

 

Design Overview

The heart of the design involves the need to be able to interpret HTML and JavaScript and any additional libraries. A web browser engine is used to perform these tasks. This allows the user interface programmer to create HTML based content just like any other web project. The difference is that input and output from the web browser engine is not necessarily targeted for a graphical desktop and keyboard/mouse. Instead, for display output, HTML elements and JavaScript variables can read from the page at any time to directly control any desired output device. For user input, push-buttons or any other sensor data can be pushed into the browser engine at any time. To create such a design involves constructing a usable workflow for these output and input tasks respectively. The workflows that have been prototyped are not necessarily the best ways but they function; there is plenty of scope for improvement. I only had limited time to think up a prototype.

 

The diagram below shows how the prototype works. All user interface related content is contained on the right side of the diagram in HTML files. This includes all text strings, images, color schemes, layout, button press rules and desired output events.

 

All hardware interfacing and all other functions that the system needs to support is contained on the left side of the diagram. Any programming language(s) could be used, and in this example JavaScript was chosen, executing on a software platform called Node.js.

 

The remainder of this blog post will refer to the right side and the left side of this diagram frequently.

html-ui-software-architecture.png

 

Note that although the right side of the diagram shows JavaScript, this is unrelated to the main program running on the left side which also happens to use JavaScript in this prototype. The JavaScript on the right side is exclusively intended for user interface related activities and it runs on the separate web browser engine called PhantomJS. The left and right sides will operate like ‘ships that pass in the night’ with the bare minimal interaction.

 

The two sides of the diagram interact with each other through the ability to remotely influence and read activity that occurs on the right side, through an application programming interface (API) available to Node.js that allows events or variables or other content to be pushed to PhantomJS by instructing it to execute any function written in JavaScript on the right side. In a similar vein it is possible for the left side to peek inside PhantomJS and read any JavaScript variables at any time.

 

For an example application, a simple procedure was devised for the left and right sides to communicate through this remote function execution and variable peeking method, and it is discussed next. But first, a brief note about the software libraries and platforms used in this project: Node.JS is fast becoming a reasonably mature platform for projects, however the module that connects it to PhantomJS and PhantomJS itself are not designed for implementing user interfaces; they are designed for testing web pages so they are being used beyond their original scope. It is hoped that over time improvements can occur as these platforms continue to be developed.

 

A Worked Example: LED Toggling

It is easier to see how all this works by examining what needs to be done for a simple project consisting of two LEDs and a single button. The project was tested with a Raspberry Pi. The idea was that the button would be used to alternately turn on the LEDs.

html-ui-hardware.jpg

 

The HTML File

The complete HTML file for the right side of the diagram is shown below (also available on GitHub). This single 45-line file contains the entire logic for the application!

The blue and red circled items are the API which we will define between the left side and the right side.

html-code-example-annotated.png

 

We can define the API as follows:

html-api.png

 

That’s it; the remainder of the HTML file contains a bit of test code that could be used to test the logic in a web browser using a debugger. No Raspberry Pi or any other hardware is required to test it.

 

The Node.js Side

The left side handles the invocation and interactivity with the right side and all interaction with hardware.

 

The code is attached to this post (it is very short, less than 100 lines), but the key snippets of it are described here.

 

The hardware interface is defined here, in terms of general purpose input/outputs (GPIO):

// Inputs
var button1=17; // GPIO17 is pin 11
var button1timer=0;

// Outputs
var led1=27; // GPIO27 is pin 13
var led2=22; // GPIO22 is pin 15
  

 

For more information on Raspberry Pi GPIO, see the Raspberry Pi GPIO Explained guide

 

The variable button1timer is used for implementing a software debounce.

 

The next step is to enable the inputs and outputs:

pi.setup('gpio');
pi.pinMode(button1, pi.INPUT);
pi.pinMode(led1, pi.OUTPUT);
pi.pinMode(led2, pi.OUTPUT);
  

 

The right side is instantiated using the following code:

phantom.create(function(ph) {
  console.log("bridge initiated");
  ph.createPage(function(page){
    page.open("file:///home/pi/development/uitest/index-simple.html", function (status) {
      console.log("page opened");
    });
  });
});
  

 

The code above launches the HTML file described earlier into the web browser engine instance. The HTML file is now running in the browser engine.

 

The debounce is handled as follows: First, a function is registered to be called automatically whenever there is a falling edge on the button input (logic level 0 means the button is pressed, logic level 1 means the button is unpressed).

pi.wiringPiISR(button1, pi.INT_EDGE_FALLING, button1int);
  

 

Whenever a falling edge is seen, the button1int function is called:

  function button1int(param)
  {
    if (button1timer==0){
      button1timer=setTimeout(button1debounce, 20, param);
    }
  }
  

 

The code above registers a function called button1debounce to be executed in 20 milliseconds. This is a switch debounce period (see the Raspberry Pi GPIO Explained guide for an explanation on debouncing).

 

Here is the button1debounce function:

  function button1debounce(_param)
  {
    if (pi.digitalRead(button1)!=0) {
      // button press was too short so we abort
      button1timer=0;
      return;
    }
    _page.evaluate(function(param) {
      buttonPress(param);
    }, function(result) {console.log("buttonPress done"); }, param);
    do_task();
    button1timer=0;
  }
  

 

Three key things can be observed to occur in the code above. Firstly as expected, the button gets debounced. Secondly examine the _page.evaluate section. This section is responsible for calling buttonPress() which is the function in the right side HTML file! This is an example of interaction between the left side and the right side. Finally a do_task() local function gets executed which will be responsible for finding out from the right side if there is any task to perform.

 

The major take-away from this section is that there is no application logic at all. All of that was contained in the HTML file!

 

The do_task function just dumbly does whatever the right side wants it to do. The _page.evaluate function is now used to query the task variable from the right side, and uses it to light up the appropriate LED, and then the right side reset() function is used to let the right side know that the task is complete.

  function do_task()
  {
    _page.evaluate(function () { return task; }, function (taskname) {
    if (taskname=="null"){
    // do nothing
    }
    else {
        if (taskname=="led1on")
        {
          pi.digitalWrite(led1, 1);
          pi.digitalWrite(led2, 0);
          _page.evaluate(function() { reset(); }, function(evresult) {} );
        }
        else if (taskname=="led2on")
        {
          pi.digitalWrite(led1, 0);
          pi.digitalWrite(led2, 1);
          _page.evaluate(function() { reset(); }, function(evresult) {} );
        }
      }
   });
  }
  

 

 

Setting up the Raspberry Pi

A folder is needed for development. One way is to create a main folder for all development work, and create a sub-folder called uitest for this user interface test. From the home folder (/home/pi in my case) it is possible to type the following:

mkdir –p development/uitest
  

 

In order to run the code, install Node.js on the Raspberry Pi using the following commands:

wget http://node-arm.herokuapp.com/node_latest_armhf.deb
sudo dpkg -i node_latest_armhf.deb
  

 

Next, in the development/uitest folder, obtain phantomjs:

git clone https://github.com/piksel/phantomjs-raspberrypi.git
cd phantomjs-raspberrypi/bin
sudo cp phantomjs /usr/bin
sudo chmod -x /usr/bin/phantomjs
sudo chmod 755 /usr/bin/phantomjs
  

 

Now some Node.js modules need installing:

npm install wiring-pi
npm install phantom
  

 

Transfer the index-simple.js and index-simple.html files into the development/uitest folder and then mark the .js file as an executable:

chmod 755 index-simple.js
  

 

Now the code can be run as follows:

sudo ./index-simple.js
  

 

Here is a short (1 minute) video of the functioning project. It can be seen that, with the limited functionality of this project, the interface is very responsive. The responsiveness with more advanced projects is for further study.

 

Summary and Next Steps

It is possible to code the entire user interface logic (and application logic if desired) in a HTML file (known as the ‘right side’ with reference to the earlier diagram) using everyday HTML and JavaScript. This is powerful because it means that tasks can be nicely decoupled during project development. A simple API can be devised that will allow the HTML file to work with the hardware interfacing code and a simple example was shown that allowed LEDs to be alternately controlled using a push-button.

 

The left side was responsible for low-level functions such as hardware control and button debouncing and for establishing communication with the right side which did everything else.

 

As next steps, it would be interesting to exercise the right side web browser engine more deeply in order to create a richer user interface that would be driven by more advanced hardware such as a graphic display, by the left side.

 

The full source code is available on GitHub.

 

Stay tuned for Part 2.

Introduction

There is plenty of jitter on signals generated using GPIO on the Raspberry Pi and many other computers, and this is due to the fact that Linux can context-switch user processes at any desired point in time dependant on its scheduler (for more information on this, see the Raspberry Pi GPIO Explained guide).

 

One solution is to use custom driver code, but this is a non-trivial exercise.

 

Another typical workaround is to offload time-sensitive I/O to external hardware such as an Arduino or (say) a hardware PWM generator for controlling servos or dimming lights more smoothly.

 

However, what about GPIO configured for input? I was curious if there was any way to improve it.

 

This short, experiment-based blog post very briefly discusses what can be done, and uses an example of building a voltmeter with the Raspberry Pi. It can be seen that with a few code-level methods it is possible to greatly improve GPIO input timing based measurements.

This is the experiment topology, it is described further below. The device on the left is a photodiode (with the usual anode and cathode connections like any diode) and it generates a small voltage whenever light falls on it.

photo-topology.png

Here is the experiment in 30 seconds:

 

Measuring Solar Cell Voltage

The Raspberry Pi GPIO Explained Guide shows examples for configuring inputs on the Raspberry Pi and using them to connect up switches. Code examples are provided in several languages. There is also a voltmeter project in that guide, which measures the frequency of pulses from a voltage-to-frequency converter integrated circuit. The integrated circuit generates a frequency proportional to the applied voltage.

The code relies on averaging to provide a more accurate result. It functions well, with very consistent measurements within a few percentage points of the expected value – not bad for a super-simple circuit.

I got my bread board ready, and connected up the input to a photodiodephotodiode. Photodiodes are small silicon devices that can be used as very miniature solar cells! Here it is in comparison to an LED:

photodiode-annotated.jpg

 

Here is the breadboard layout:

photodiode-circuit.jpg

 

For the full circuit diagram and details, see the GPIO Explained guide. The only difference is that I’ve added the photodiode anode connection to the circuit input, with the cathode connected to 0V. You could also optionally add a small 47nF capacitor across it, in case the room lighting has any flicker. The black square-shaped photodiode can be seen plugged in on the right side of the breadboard, close to the row marked 15. A clear photodiode (rather than a visible-blocking, infra-red pass filter version which is what you can see in the photo) would have been better for room lighting measurement, but it was all I had and it still worked.

 

I was expecting a voltage of around 250-350mV to be generated by this tiny photodiode/solar cell in normal room light (and this would cause the voltmeter circuit to generate a frequency of 2.5-3.5kHz), and I wanted to measure it using the Raspberry Pi. I could then log the voltage generated during the day, or see if someone switches a lamp on in the room, or place a couple of the photodiodes in series, and so on., as mini science experiments. But then I got curious about how to improve it.

 

The first addition was to write some code (which will be published in a few days after some tidying) to plot the measured voltage every second. Basically the code runs a small web server on the Raspberry Pi, and draws a graph if anyone types the IP address of it into their web browser. I can view it on any web browser running on the Raspberry Pi, or my laptop, or mobile phone. The x-axis shows in seconds how long the experiment has been running, and the y-axis shows the measured voltage. This was the result in normal home lighting conditions:

solar-chrome.png

 

Stressed Out

There is also a nice stress test program that can be installed (type sudo apt-get install stress ), and you can use it to provide the cores on the Raspberry Pi with useless time-consuming things to do. You can see the CPU consumption shoot up to close to 100% on any number of its cores, or all four cores if you wish.

 

To use it, this command stresses out all 4 available cores, for 60 seconds. Press Ctrl-C at any time to quit:

stress --cpu 4 --timeout 60

 

If you type top –d 1 in a command window, you’ll see a list of processes and their current CPU usage. Press ‘q’ to quit at any time.

top.png

 

Try running the stress program while the voltmeter is running, and the calculated voltage becomes very inaccurate because now the scheduler needs to make CPU time available for the stress program’s tasks (processes). Here is what occurs:

solar-fluctuate-stress.png

 

Sleeping, Averaging, Voting, Scheduling!

I experimented with a few tricks to try to get more consistent measurements.

 

One trick was to force a sleep before computing the frequency. The theory was that the scheduler might be unlikely to context-switch immediately after the sleep function, provided the sleep was long enough to allow the scheduler to enable some other process run. The theory failed - I didn’t get good results with this method; it seemed to have no useful effect.

 

Another trick was to still use averaging, but now also implement a ‘voting’ method. The plan of attack was that for slow-changing voltages, the code would calculate three sets of averaged values in quick succession, and then ‘average the averages’ by using two of the averaged values out of the set of three, and discard one out of the three.

 

But which two to choose? The chosen two would be the ones that are most agreeable, i.e. are numerically closest to each other. I figured I was in good company because this is approximately how the space shuttle computers worked. This voting method improved results somewhat!

solar-averaging-voting.png

 

Note that mathematically it would have been very useful to plot a probability density function from multiple results and see what the distribution reveals about scheduler impact to the measurements, but I didn’t explore this in the very short amount of time I had. It would be an interesting experiment though.

 

The next method was to attempt to influence the scheduler; it is possible to dynamically influence the priority and scheduling algorithm on-the-fly with Linux. I selected a policy called SCHED_FIFO and set the priority to the highest value. Here is the C code that can perform this:

 

#include 
#include 
#include 
#include 


int
main(void)
{
  struct sched_param sp;
  int ret;
  sp.sched_priority=99; // (0..99) highest priority is 99
  ret=sched_setscheduler (getpid(), SCHED_FIFO, &sp);
  if (ret!=0)
  {
    printf("Error setting scheduling policy\n");
  }
  // rest of your program
  
  return(0);
}

 

The results were much improved (see screenshot below). With great power comes great responsibility, and it is strongly advised that code runs to completion quickly (or changes the priority again dynamically) and that code should be simple enough that there is low risk of it hanging for a long time.

solar-sched-fifo.png

 

Summary

No high-end instrumentation would do this, but if you want to use Raspberry Pi inputs for home-science-experiment-grade timing applications, consider scheduler, averaging and voting techniques! It was a lot of fun to measure the small solar cell voltage with such a simple circuit connected up to the Pi, logging away.

Note: XMP-2 also has a virtual simulation, check it out by clicking here.

 

Introduction

The ground-breaking XMOS startKITXMOS startKIT is an ultra-low cost near-credit-card sized board designed for real time operations. It was launched about a year ago at a very low cost (£12 including VAT) as a processor board intended to connect to the Raspberry Pi and XMOS went on to distribute thousands of startKITs for free.

 

Together with the Raspberry Pi one of the boards was used to create a robot called XMP (XMOS Mobile Platform). Version 1 of the robot was quite primitive and really just a proof-of-concept type of project.

The brand new XMP-2 robot was made possible thanks to another startKIT from john_xmos at XMOS and a Raspberry Pi courtesy of doctorcdf at Element14. Here it is at the Element14 stand at Embedded World 2015 in Germany, manned by an Imperial Stormtrooper (click here to see a video of it in motion – 1:40 into the video):

robot-front.jpg

 

XMP-2 is not complete yet (it is a 1-month old baby yet has already turned to the dark side) and is currently missing sensors and will eventually have a custom PCB too. Distance measurement will be based on a camera and laser arrangement.

 

It was built in a few evenings due to needing to be shipped to Germany quickly. It relies heavily on Lego for the electronics attachments. However the chassis, wheels, ball rollers and axles are constructed from aluminium and steel for a rigid and reusable base for experiments.

robot-part-assembled2.jpg

 

Circuit Overview

The diagram below shows the main components used; click to enlarge.

xmp-2-overview-diag-2.png

 

XMP-1 relied on continuous rotation hobby servos which are fairly inaccurate. XMP-2 uses brushed DC motors and Infineon H-bridges to power them. All motor control occurs using the XMOS xCORE processor. For closed loop feedback encoders are used. These are connected to the XMOS board so that the xCORE processor can count pulses (tens of thousands of pulses per second - around 60k pulses per wheel revolution in this design) as the motor turns, calculate appropriate pulse width modulation (PWM) which then drives the motors through the Infineon H-bridgesInfineon H-bridges. The closed loop feedback means that the robot can make movements with accuracy and allows for motion even at slow speeds where open-loop PWM in ineffective as soon as the motor encounters a load. For more detail on closed-loop PWM and control of brushed motors, check out this post which used a BeagleBone Black for controlling motors. To get a basic understanding of different motor types click here. There is also a post on the Infineon DC motor control H-bridge boards which were used.

Click here for a video showing a practice run of just the motor control portion (before the robot was complete).

practice-run2.jpg

 

XMP-1 required two power sources. This time round a single battery source (initially non-rechargeable batteries) is used to power everything. To further simplify things, a custom PCB will be created at some point to replace the mass of wires and also provide a rechargeable battery solution.

 

The entire robot (including motors, XMOS board and Raspberry Pi) is powered using six AAA batteries.

 

The XMOS board was used to control the motors while relying on feedback from the encoders. Another aim is to eventually implement a vision system to be able to navigate around objects autonomously.

 

Mechanical Overview

A classic differentially steered design was created with two wheels that are driven by the motors and the speed and motor direction can be controlled. The third wheel (unpowered) was actually a ‘ball transfer unit’ (from Alwayse Engineering,  model 7101) which is a bit like an old computer mouse ball but usually operated in the inverted position for conveyer type systems. Another ball transfer unit was used for stability and becomes the fourth wheel.

 

The motor unit has built-in gearing and a built-in encoder – it is available new from Faulhaber (Series 1524..SR) and is also available in used/repaired condition via eBay from several sellers. It is further geared down using a gear from motionco – primarily to decouple the motor unit from the output shaft for reliability but also to reduce the motor speed and increase the torque. Everything is held together using a motor/gear assembly block made from plastic. To build something similar schools/colleges may have a machine shop or a 3D printer and accurate drill press could be used (sub-millimeter accuracy is needed to mesh the gears properly). Don’t forget to wear eye protection.

 

The slide show below shows the motor/gear assembly block construction and how it was fitted to the chassis. The wheel shaft and bearings were from motionco too. It was decided to have a 4mm diameter output shaft to the wheels. The chassis is built using aluminium extrusions (available from eBay) with rounded edges – far safer than the XMP-1 design.

{gallery:autoplay=false} Motor/Gear Assembly Block Construction

motor-mount-annotated.jpg

Assembling the block: The motor can be seen inserted at the right

motor-mount2-annotated.jpg

Mounting the motor: The motor fits into a part-bored hole and is secured with two small bolts. There is a small recess for fitting a bearing for the axle

nuts-bolts.jpg

Attachment to chassis: The center hole shown here is bored to two diameters, one for passing the axle through, and the larger diameter is for fitting another bearing

gear-and-hole.jpg

Axle and Gear: The gear is glued to the shaft

The photo below shows the assembled chassis with the motor/gearbox blocks mounted, a ball transfer unit and lenseslenses and laser.

chassis-motors-mounted-rr.jpg

 

Engineering Drawings

If you’re building a replica and intend to closely follow the design, then the slideshow below contains the detail on how to construct the motor/gearbox mount and chassis:

{gallery:autoplay=false} Engineering Drawings

gearbox-design-2.png

Motor/Gearbox Block: Poor diagram but it gets the point across hopefully; dimensions from the rear of the block

gearbox-design-1.png

Motor/Gearbox Block: View from side

gearbox-layout.png

Motor/Gearbox Block Assembly: How the bits fit together

chassis-layout.png

Assembly: This photo shows how the motor/gearbox block, axle and chassis fit together

Lego Integration

Lego was instrumental to mounting most of the electronics. It allowed the design to be implemented quicker without needing to worry upfront where precisely all the boards would be mounted. The photo below shows how the XMOS startKIT was mounted. Two white 4x1 blocks were drilled and screws were used to secure the XMOS board to them. In the photo below, the stripboard on the left contains all the power supply circuitry.

xmos-board-annotated.jpg

 

The stripboard and the Infineon boards were also mounted using Lego; they were glued into notches cut in Lego as shown in the photo below:

inf-motor-changed-cap.jpg

 

Putting it all Together

The slideshow below shows what the robot looks like from various angles (laser and headlights powered up in some of the photos):

{gallery:autoplay=false} XMP-2

robot-front.jpg

Front View: Laser powered up

robot-front-zoomed.jpg

Front View Closeup: Stormtrooper keeping watch

robot-rear.jpg

Rear View: The XMOS startKIT can be seen here. It has a 3x3 matrix of LEDs which could be used for status/notifications

robot-side.jpg

Side View: 'Micromouse' style wheels were used

robot-front-lit.jpg

Front View: Headlights lit up!

The XMOS board can be seen close-up below:

robot-detail-xmos-annotated.jpg

 

The Raspberry Pi can be seen installed in the photo below:

robot-detail-rpi.jpg

 

Another photo of the power supply board:

robot-detail-supply.jpg

 

Schematics and Source Code

There really isn’t a lot to the schematic currently that cannot be deciphered from the circuit overview shown earlier in this post. As soon as a schematic is created, it will be published here. Meanwhile, for any technical questions regarding the circuit, please ask in the comments section below. No schematic was created because of the very rapid prototyping that occurred for this project (any parts used were just thrown onto the stripboard!).

 

The source code will be published once tidied up (this might not happen for a while – please ask if you need the raw code, I’ll be happy to share it). A similar scheme was followed as for XMP-1, where the Raspberry Pi implements a web server and the XMOS board implements all motor control.

 

There is a three-part guide to the XMOS startKIT that hopefully helps understand how to use it. Part 1 is a general guide to the startKIT for newcomers. Part 2 covers the serial peripheral interface (SPI) communication between the Raspberry Pi and startKIT. Part 3 provides another SPI example amongst other things.

 

Update January 2016 - Detail Photos

Here are some more photos of the circuitry. A DC-DC converter DC-DC converter was used to provide 5V for the processor boards. It is the box-shaped component in the photos. A small 3.3V LDO regulator3.3V LDO regulator was used to power some logic gates for the rotary encoders. The power switch can also be seen soldered onto the stripboard above the DC-DC converter. Red dot indicates powered on position!

xmp-2-vero-front.jpg

 

Another view. A few electrolytic capacitors are used as recommended by the DC-DC converter and LDO datasheets. A few ceramic caps are on the underside (not shown).

xmp-2-vero-front-view-2.jpg

 

The wiring may look messy but it was mostly color-co-ordinated and easy to follow. Notice the XMOS StartKit has had header pins soldered on the rear of the PCB, not the front side, for ease of assembly (and I wanted the LED array on the XMOS StartKit to face the other side).

The red Infineon boards can be seen glued into notches cut in the white Lego pieces. The StartKit was bolted using holes drilled in Lego, so it is easily removable.

xmp-2-angle.jpg

Side view. The large electrolytic capacitor that is present on the Infineon boards by default was reduced in value due to the low current requirement of the motors that were used.

infineon-view-xmp-2.jpg

 

Laser Ranging

The photos below show the principle that could be used for laser ranging.

The first photo here shows the default view against an example (cardboard) wall. The laser beams a line pattern (it has a special lens to do this):

xmp-2-laser-action.jpg

This next photo shows what occurs when a Stormtrooper is positioned between the laser and the wall. Notice the horizontal laser projected line has been cut, and is reflecting off the Stormtrooper:

xmp-2-laser-action-example.jpg

From the height difference between the horizontal line off the background wall and the reflected line off the Stormtrooper, it is possible to deduce that an obstacle (the stormtrooper) exists, and the deduction can be done with very little image processing needed.

laser-ranging-height-annotated.jpg


What’s Next?

XMP-3 will be next. It will reuse the same base as XMP-2, but will have increased functionality – primarily a robot arm – and will use a PCB to replace the stripboard (and will therefore have a schematic).

 

Summary

XMP-2 is a completely new robot, very different from the XMP-1 prototype. It has fairly accurate motion thanks to closed loop control and is therefore a suitable platform for attaching sensors and vision. The XMOS startKIT was key to monitoring thousands of pulses per second from both motors and using them to control the motor motion. The Infineon H-bridges, although overkill for this particular robot, were selected so that the robot could be scaled to larger sizes easily without needing many schematic modifications.

 

The base will serve as a suitable platform for XMP-3 - stay tuned!

 

xmp-2-laser-darth-vader.jpg

Introduction

Every lab (home, office, school) needs temperature measurement capabilities. Measuring temperature for science experiments is hard – all sorts of materials, liquids, and chemicals may be involved or a large temperature range may need to be covered. The sensor used for this (a thermocouple) is not easy to interface, and the sensor amplifier is non-trivial since it has to be able to measure an extremely small voltage.

 

For flexibility in the science experiments that it can be used for, high accuracy is needed along with a fast response and good update rate. It goes without saying that data should be logged in a convenient form, and it should be easy to use.

 

For convenience there are ready-built temperature measurement and logging products out there, sometimes they are not easy to use due to soft-button overload and a limited display. In addition for large lab or classroom use information should be logged and retrievable by people easily – and perhaps view the current status on a large screen. It also goes without saying that some experiments may take a long time, so the ability to check up on your experiment using a mobile phone during lunch is useful too. One last requirement was that this should be easy to build even for people new to electronics and software.

 

This project shows how to connect up a thermocouple board to a Raspberry Pi (RPI), and use it for temperature measurement and logging with great performance and ultra-low cost. This project is easy – no soldering required unless you want to. This is also a great project to start using the 'DIL (dual-in-line) header'  connector on the RPI if you have not already done so.

rpi-insert-functionality.jpg

 

Here is a video showing the entire project in action; the brown cable is the temperature probe.

 

Design Overview

A lot of thermocouple-based hobbyist projects use the MAX31855 integrated circuit and ready-built ‘thermocouple amplifier’ boards are available for connecting to the RPI from several suppliers. This project however uses the far higher-resolution ADS1118 from Texas Instruments. It comes in a surface-mount package but fortunately a ready-built ADS1118 development boardready-built ADS1118 development board is available which contains all circuitry including a LCD display and thermocouple - it is extremely good value for money. If you don’t fancy soldering then it is possible to connect up this board to the Raspberry Pi (or any other computer board – it uses a standards based communicaton method called Serial Peripheral Interface or SPI) using eight jumper wires (male-to-female cables are needed). Alternatively, if you don’t mind a soldering exercise then a small adapter board can be constructed. This was the approach taken here. In summary you can see in the photo below all the bits that are used for this project, including the assembled adapter board.

therm-items-unplugged.jpg

 

The entire project can be controlled via a web browser or from the command line.

therm-project-powered.jpg

 

To build the adapter board, the simplest way is to use a circuit board; using EAGLE software I drew up a design for which the files are attached to this post ready to send off to a PCB manufacturer (it costs about $30 for ten boards).

therm-pcb.jpg

 

Alternatively, prototyping board can be used; I obtained some perf-boardperf-board (the type with isolated pads, not stripboard) and cut it to size. A 3mm hole was drilled for attaching a support pillar (threaded hex spacer)support pillar (threaded hex spacer). The boards are next to each other, not on top of each other, to minimise temperature change and noise issues, both of which would have an effect on the thermocouple reading.

 

The next step was to solder a  40-way DIL header socket  40-way DIL header socket.

therm-bits-assembly.jpg

 

I wanted the ability to plug in the ADS1118 board onto the pad side of the perf-board, so there is a slight complication here. The solution was to use bent SIL headers. 10-way SIL headers10-way SIL headers are needed (the photo shows 8-way which is what I had at hand) - or use surface mount ones which are similar but with the bent ends alternating on either side. If you are using a circuit board and not perf-board, then straight SIL headersstraight SIL headers are needed.

 

To get them aligned, plug them into the ADS1118 board, and position it over the perf-board and then tack a few pins with solder. Then the ADS board can be very gently unplugged and the SIL headers can then be soldered properly. Note that at this stage it is quite difficult to unplug without tearing the pads off the board. Hold the bent part of the SIL headers against the board while unplugging the ADS1118 board.

 

Next, to make the SIL headers very secure, solder each pin to as many pads as possible (each one can be soldered to three pads).

therm-adapter-solder-side-detail.jpg

 

The next step is to wire it up. I used Kynar wireKynar wire which is very thin but any wire will do.

therm-adapter-wire-side.jpg

 

To identify the connections, refer to the pin numbering photo below and the following table:

* Connections:
* TI board       RPI B+
* ------------   ------------------
* P1_1  VCC      1     3.3V
* P1_7  CLK      23    CLK
* P1_8  ADS_CS   26    SPI_CE1
* P2_8  LCD_CS   24    SPI_CE0
* P2_9  LCD_RS   11    GPIO_17_GEN0
* P2_1  GND      9     GND
* P2_6  SIMO     19    MOSI
* P2_7  SOMI     21    MISO
      

 

therm-pin-numbering.jpg

 

After testing the software and board functionality, it is possible to use some epoxy resin glue (e.g. Araldite) to make the SIL headers even more secure. A minimal amount was used so that it was possible to still just-about solder onto the pins if needed to in future.

 

With the PCB approach mentioned earlier, when the PCB arrives, the header pins and receptacle can be soldered, and it is an easy task (takes five minutes) so the PCB is the preferred method especially if you need to make many of them (I intend to make several). I used DIL header pins instead of SIL, but either will work with the PCB layout attached to this post.

bp-adapter-top.jpg

Here it is attached to the RPI:

bp-adapter-rpi.jpg

Underside view:

bp-adapter-underside.jpg

 

 

Software

The diagram here shows the entire solution overview. The majority of the code is in three files. The code that interfaces to the ADS1118 board is discussed first, because it is possible to run this code standalone if desired. It is shown in purple in the diagram.

therm-solution-overview.png

 

To create the software, the first thing one of the things to do is to create a logo:

/**********************************************************************************************
* therm.c
 RPI  430BOOST-ADS1118 Thermocouple/LCD Board 
*
*         __                                __     ____   _____
*   ____ |  |   ____   _____   ____   _____/  |_  /_   | /  |  |
* _/ __ \|  | _/ __ \ /     \_/ __ \ /    \   __\  |   |/   |  |_
* \  ___/|  |_\  ___/|  Y Y  \  ___/|   |  \  |    |   /    ^   /
*  \___  >____/\___  >__|_|  /\___  >___|  /__|    |___\____   |
*      \/          \/      \/     \/     \/                 |__|
*                                                          
      

 

The next step is to make use of the wealth of code that TI usually offers. In this case, TI already had high quality ADS1118 code intended for the MSP430 Launchpad that could be reused. It was adapted slightly to be usable on the RPI, using some input/output (I/O) code from Gert van Loo and Dom.

 

Temperature measurement may seem to be an easy task (read an ADC value and convert to temperature) but thermocouples require ‘cold junction compensation’ which in the case of the ADS1118 means reading an internal temperature sensor too. The code interleaves reading the internal sensor and the external thermocouple. Another key point is that a thermocouple output is not linear compared to temperature; thermocouple manufacturers publish data that can be used to get a more accurate conversion from ADC value to actual temperature. The TI code already includes these capabilities for the supplied thermocouple.

 

The code was adapted to add logging capability. Since the board is to be powered by the noisy 3.3V supply from the RPI, and it is in close proximity to the RPI, some steps need to be taken to ensure that the measurement is cleaned up. The implemented algorithm every second reads the internal temperature sensor once, and the external thermocouple ten times in a short burst (a few hundred milliseconds total) so that the measurements can be averaged and finally output to 0.1 degrees C resolution. The end result was very good; see some example output here.

 

The LCD has two lines of 16 characters, so it was decided to use the bottom line to display the time and current thermocouple temperature. The top line is user-dependent; it can be set to something so that people immediately know what the experiment is about. For example, it can say “Test #1” or “Don’t touch’.

therm-project-lcd.jpg

 

Using the code is easy.

 

First off, confirm that some features are enabled on the RPI. If the RPI is being used fresh, then after operating system installation, ensure that the ‘Advanced’ menu option is selected and then enable three things: SSH, SPI and I2C - we don't use all these for this project, but they are standards based interfaces that should always be enabled unless you never want to unplug the RPI from a monitor or not make use of the 40-way DIL connector on the RPI. If this was not done after OS install, then type raspi-config in a text window (also known as a command shell) on the RPI and then select ‘Advanced’ in the menu that appears.

 

Assuming the three features mentioned above are enabled, then create a folder for your work off your home directory (e.g. create a folder called development and then a sub-folder called therm) and copy the source code (stored at github.com) into that sub-folder.

Here is how to do all this:

therm-compile3-1.png

 

To compile the code (also shown in the screenshot above) type:

gcc -o therm therm.c -lrt
      

 

The code is now ready to run. There are a few ways to use this project. One way is to just type commands into the command shell. Another way is to use a web browser. These two methods are discussed next.

 

Command Interface

The code can be run either using ‘sudo’ or as superuser (root) user.

For the latter, to become root user, first type sudo passwd root one time, and create a superuser (i.e. root user) password. Now, whenever you want to become superuser, you can just type 'su' and enter that password. To exit out of superuser privileges at any time, type 'exit'. Some people prefer sudo, others feel it is an unnecessary handcuff.

 

sudo ./therm
      

 

or (using the root user method)

sudo passwd root
su
./therm
      

 

The temperature will be displayed.

There are other variations, of which some are listed here. For example to dump the temperature every second to the command shell, type:

./therm 1
      

 

The command above will indefinitely dump temperature to the screen. To stop it at any time, press Ctrl-C.

 

To log the data, type:

./therm 1 mylogfile.csv
      

 

Press Ctrl-C to stop logging, and the generated file can be viewed and graphed using spreadsheet software (e.g. Excel).

 

To print some text to the LCD display, type:

./therm msg “Experiment #1”
      

 

or combine it with a filename to start logging too:

./therm 1 mylogfile.csv msg “Logging…”
      

 

Using a Web Browser

To use web browser capability, a platform called Node.js is run on the RPI. There are plenty of projects on Element 14 using Node.js with the RPI or BeagleBone Black. To avoid repeating, just follow the Node.js and Socket.IO install steps at this location (scroll to the section "Raspberry Pi web server and application software") and follow all the steps listed in that section up to and including the command ‘npm install socket.io’.

The code that will be used to enable web control is shown in blue and orange in the diagram below:

rpi-software.png

 

To run the web server/application software, type

node index.js
      

 

Now you can navigate using a web browser to http://xx.xx.xx.xx:8081/index.html to see the web page. Click ‘Live’ to see the live view of temperature.

live-view.png

 

Select a file name and click ‘Log’ to start logging data.

 

Summary

Thanks to TI’s skilful engineering with the ADS1118 board, a very high quality science lab temperature-logging instrument can be quickly assembled, ready to run interesting experiments. See the coffee cup blog post for an example.

 

The software is fresh and really just proof-of-concept level and will have a few bugs but it appears to work reasonably well in the limited testing I have done so far (I used it to log data for a few hours). It would be wise to do a practise run before trying to use the software in a classroom.

 

Although I have no means to measure accuracy, TI have published a PDF document about precision thermocouple measurement with the ADS1118 which shows the techniques they used to ensure an accurate result. It is reassuring to see the output using the board and algorithm appears clean and as expected.

 

For quick results, use the PCB design attached to this post, but the proto-board method works well too.

bp-adapter-rpi-running.jpg

 

Additional Ideas

If desired (e.g. outdoor use), the solution can be powered from a Lithium Polymer (LiPo) cell. To do this, a BatteryBoosterPackBatteryBoosterPack is inserted in-between the adapter board that was created, and the thermocouple board. Here is what it looks like:

therm-batt-powered-annotated.jpg

The Battery BoosterPack comes with the LiPo cell. Note that some slight modifications need to be done to the Battery BoosterPack before it is used for this project, in order to prevent any pins from clashing. See this blog post (scroll to the section titled "Battery Power" and perform the steps in that section).

 

Source Code

Code is available on GitHub, click here. The initial version has functionality to display temperature on the LCD display and on the browser dynamically, and also initiate logging (and displaying temperature). It is experimental code, and will need enhancements; currently it is not possible to stop the logging if started, except by going to the command line.

 

It has some bugs, such as if multiple users connect to the browser, expect occasional erroneous values of 0 degrees C on the display briefly if multiple users connect and the system is not logging (if the system is logging, this issue does not occur). Also it may display 'error' briefly when connecting. It continues to function.

 

There are no known issues with the actual measurements and the logging functionality, however if you are planning to run a very long (multiple hours) experiment, it would be good to have a dry run first, to confirm the system functions for an extended time - I only ran the system for an hour or two at a time. Also, you may wish to log less frequently in that case (currently it logs every second).

Introduction

This project provides “oscilloscope-like” capabilities for the ultra low cost of £12, with near-zero soldering required. It’s not a very practical oscilloscope (and this project is really just a quick proof-of-concept written in a couple of evenings) but the information here may be reusable for analog sensing applications and for any other projects that require plotting data to a screen. It could possibly be useful as-is to demonstrate low frequency waveforms in a teaching environment where a real oscilloscope is unavailable. The oscilloscope output is viewed in a web browser, so it is possible to project the output onto a large screen for example. The 12-bit resolution helps here too. All source code is published at the end of this post.

Here is an example video, showing a real signal from a 555 based circuit (it was a sawtooth circuit, click here to download if needed). You can see that it is quite responsive, with multiple refreshes per second.

 

Here is another video, showing a sine wave signal being ramped up in frequency:

 

To construct, all that is required is an XMOS startKIT boardXMOS startKIT board (less than £12, or free if you obtained one during the XMOS giveaway at the start of the year) and some wires (and a Raspberry PiRaspberry Pi as tested here, but other boards such as the BeagleBone Black or RIoTboard would also work).

xae-sinewave.png

 

What is the XMOS startKIT?

The XMOS startKIT is a compact (slightly larger than a credit card) board that contains an XMOS multi-cored processor. It has a number of distinct advantages over other processors that make it ideal for projects that require real-time operations. The chip also contains a built-in analog-to-digital converter (ADC). Having all this on a single £10 board makes it attractive for data logging capability. Here is a photo of the setup, showing the startKIT connected up to the RPI.

xae-setup.jpg

 

The startKIT is powered and programmed using a USB cable. Information on how to do this is in an earlier post. Not shown in the photo, if desired, both the startKIT and the RPI can be powered from a single USB supply connected to the startKIT board. The RPI doesn’t need a USB supply. To achieve this, connect a wire from the startKIT connector labelled J8 pin 13 (5V) to the RPI connector pin 4.

 

Why is an Oscilloscope useful?

In a nutshell it allows you to graphically see electrical signals over time, at rates far higher than a multimeter could show. A multimeter may read one value, but observing the detail over time using an oscilloscope may reveal a very different picture. This project here is not really an oscilloscope, however it does attempt to implement some oscilloscope-like features such as trigger capability and sweep modes and on-screen cursors for trace measurement. It is lacking in good sample rate, any front end filter and in fact it is lacking the entire front half of a real oscilloscope which would normally include AC/DC input capabilities and gain adjustment. Since it is not really an oscilloscope, from now on it will be referred to as the XMOS Analog Examiner or XAE. It can be used to examine simple circuits at low speed. Higher sample rates require more hardware. An example project is here using a BeagleBone Black which achieved around 20 million samples per second. It is still not a complete oscilloscope though. Real oscilloscopes have come down in price, and it is possible to purchase a practical one new for £200 upward. For a new center at my workplace, we are purchasing multiple oscilloscopes. The lowest cost one we have selected is a Tektronix TBS1052BTektronix TBS1052B because it offers dual channels at 50MHz for a reasonable cost and we wanted one that can be taken home by employees. There are lower priced options, but we liked the high-resolution display on this model and the usual Tektronix reliability.

 

XMOS startKIT: More Information

If you’re interested in finding our more about the XMOS startKIT, the two links that follow may be useful. This is part three in a series of posts on the XMOS startKIT. The XAE 1000 here is a by-product that, while not a practical oscilloscope, was used to try out the analog capability of the XMOS board.

 

Part 1 entitled XMOS startKIT: Introduction, Terminology/Architecture, Getting Started and Example Programs covered the following topics:

  • Introduction/Terminology/Architecture
  • Running Tasks in Parallel
  • XMOS and IoT
  • Installing the development environment xTIMEcomposer
  • Building and running an Example Program
  • Example: Controlling a Servo
  • Example: Multi-tasking
  • Troubleshooting/Debugging

 

Part 2 was called XMOS startKIT: Building an XMOS and Raspberry Pi Robot XMP-1 and it covered a few different things. In particular it introduced a general-purpose framework to connect the XMOS startKIT board to the Raspberry Pi using the Serial Peripheral Interface (SPI). This capability was used to construct a robot. Part 2 covered these topics:

  • Robot introduction. Hardware and Software overview and Circuit/Wiring diagram
  • Serial Peripheral Interface (SPI) introduction
  • Connecting the Raspberry Pi to the XMOS startKIT
  • SPI implementation on the XMOS and Raspberry Pi boards
  • Implementing multiple servo control
  • Creating a Raspberry Pi web server and application using Javascript and Node.js
  • Hardware assembly of a robot

 

Part 2 covered methods of transferring data from the Raspberry Pi (RPI) to the XMOS board, such that servos could be controlled from a web server running on the RPI. This part 3 now covers how to use the general framework from part 2 to transfer data predominantly in the opposite direction; analog data is collected by the XMOS board, and is transferred to the RPI for display to anyone connecting to the XAE application using a web browser.

 

Solution Overview

The next two diagrams below shows the overall solution. The circuit diagram is extremely simple; just a few wires are used to connect up the two boards:

wiring-diag.png

 

Analog data is collected by the startKIT board and this information is passed on demand to the Raspberry Pi (RPI) shown on the left. The RPI runs a web server and passes data to the user’s web browser. All graphical processing occurs in the browser. The major software components are shown below:

solution-overview2.png

The details are discussed next, beginning with the XMOS portion.

 

XMOS software overview

The XMOS chip provides the capability to run multiple tasks in parallel. This capability is described in the first blog post. In summary different code can execute on different XMOS cores, and communication can occur between the XMOS cores using a concept known as ‘channels’.

 

The XMOS multi-cored chip also contains a built-in 4-channel analog to digital coverter (ADC). It is capable of 4096 points of resolution (12-bit) at 1 million samples per second (MSPS).  The ADC is controlled by the XMOS core using the ‘channel’ concept too. Channels were covered early on in part 1.

 

In this project, just three XMOS cores are used. One XMOS core runs a task called ‘spi_process’ which is used to handle serial peripheral bus (SPI) input/output between the XMOS device and the Raspberry Pi. Another XMOS core (running adc_task) is used to retrieve ADC captured data into a buffer of memory. A third XMOS core runs a task called ‘app’. It sits in the center and is used to retrieve the buffer data and pass it to the SPI core, and to handle trigger and sweep adjustments. The RPI can send specific instructions to make adjustments such as trigger type. These instructions are decoded by the app task. The diagram below shows the three tasks in purple, and some example message sequences below for retrieving ADC samples and for setting parameters such as the trigger level. This diagram makes more sense after reading part 2.

xmos-software-arch.png

The adc_task collects 500 samples at a time (enough for one screenful) but only stores to a buffer if the trigger condition is met. A very simplistic trigger capability was implemented, and it is still buggy. It works just-about ok with most waveforms, but doesn’t maintain triggering so well with square waves. The video here shows several different types of waveforms (the view from a real oscilloscope is shown on the left for comparison). I didn’t spend much time refining the trigger capabilities.

 

Note that when using the attached code, the ADC needs to be enabled in the Makefile. This is done by double-clicking on ‘Makefile’ to open it, and then appending ‘-fxscope’ to the flags as shown in the screenshot below (make sure this is done for ‘Release’ and ‘Debug’) and then saving it.

enabling-adc.png

 

Also, note that the ADC software that I used (it was found in a community tab inside the XMOS development environment) relies on an external trigger to capture data, and the trigger is hard-wired to a particular pin on the startKIT board. This means that to use SPI as well as the ADC, a different pin needs to be assigned for SPI MOSI compared to post 2 SPI wiring). The circuit diagram in this post shows that the selected pin for SPI MOSI on the XMOS board was connector J7 pin 4 which is the pin marked D12 on the startKIT silkscreen print.

 

Raspberry Pi software overview

Much like post 2, this project was predominantly coded using JavaScript because the same language can be used twice; in the web browser and on the Raspberry Pi server. It saves having to learn two languages. Node.js (the platform which will allow JavaScript to run on the RPI) and Socket.IO (the feature which will allow real-time communications between the RPI and the user’s web browser) were installed on the RPI (see post 2 for details on how to do this). A very simple C program called xmos_adc was written to handle the low-level communication to the XMOS board; it is responsible for transmitting values across the SPI interface to the XMOS board and dumping the result onto the command line.

So, to retrieve 500 samples of analog data (enough for one screenful), the following commands could be typed on the command line, where the parameter shown is a tag value:

./xmos_adc 3
./xmos_adc 0





The first command instructs the XMOS board that the Raspberry Pi wants to retrieve data. The second command retrieves the samples. As soon as the samples have been retrieved, the XMOS board begins to collect 500 more samples ready for subsequent collection.

 

To adjust the trigger or sweep settings, different parameters can be used.

As an example, to set the trigger level to a midpoint, the following command can be used, where for the second parameter, the range of 0-3.3V is represented by a number in the range 0-255:

./xmos_adc 6 127





 

Here is another example. This selects the trigger direction where 0 means rising, and 1 means falling:

./xmos_adc 8 0





 

Notice that the tags are mostly even numbers; a convention was used that even numbers would alert the XMOS board that no response was expected. An odd tag means that the RPI expects a response in the next SPI message. This convention was created in post 2.

 

The xmos_adc code doesn’t do anything more; all of the main logic is implemented in JavaScript. The code that is to run on the Raspberry Pi is written in a single file called index.js. It is responsible for functioning as a web server, serving up the index.html file to the user, and taking instructions from the web browser via Socket.IO and translating into xmos_adc command line instructions. Whatever xmos_adc returns is passed using Socket.IO back to the user. The code is very basic.

 

Most of the interesting stuff is coded in the HTML file. This code will run inside the web browser.There are many ways to improve the code, and the user interface too. The code should be considered just as a proof-of-concept. As soon as a connection is established using Socket.IO, the browser sends instructions to the web server to invoke retrieval of the ADC sample values. The HTML file then instructs the browser to display the screen and then immediately collect more samples. This repeats indefinitely. The process runs as fast as possible, so that the waveform refresh speed is dependent on the user’s computer and web browser. If any button is clicked, then temporarily this refresh scheme is paused while the instruction is sent to the Raspberry Pi for onward forwarding to the XMOS board, and then the sample retrieval is resumed. All graphical calculations are performed in the web browser. It means that very little processing is done on the Raspberry Pi. A JavaScript library called D3 was used to display the waveforms. Some interesting features were found possible to implement, such as direct placement of the trigger and cursors by just clicking on the display. If the user clicks on the left side of the waveform display, the trigger position is updated. If the user clicks at the top or the right side of the display, time or amplitude cursors will get displayed in red. You can see some time cursors and the trigger position in red in the waveform display at the end of this post.

 

Summary

This post completes the investigation into how to implement bidirectional information exchange between the Raspberry Pi and the XMOS startKIT board, and also examined ADC input. It was shown that JavaScript can be used to provide a very responsive user interface. Although the final XAE 1000 implementation is a novelty oscilloscope and not a true oscilloscope, it may serve some useful purpose perhaps for simple circuit demonstrations.

xae1000-triangle-wave.png

 

Source Code

See here for the source code.

(Note: Click here to see XMP-2!)

 

Introduction

The XMOS startKIT from Farnell (or Newark) is a very low cost (£12 including VAT) processor platform that works well with the Raspberry Pi. Together is possible to construct robotics applications with almost no soldering required.

 

xmp-photo-rear.jpg

The XMOS startKIT is a near-credit-card sized board with an XMOS chip on it with multiple ‘XMOS cores’ that can be programmed in C.  XMOS technology allows things to run in parallel at high speed with low jitter. These are exactly the characteristics which could be ideal for robotics applications.

 

Together with some code to run on the XMOS startKIT board and on the Raspberry Pi (RPI), the boards are used to construct a simple compact mobile platform (I’m going to call it XMP, XMOS Mobile Platform instead of a robot from now on in the XMOS spirit of preceding everything with ‘X’).

 

Although the XMP-1 is not much of a robot until it has some sensors and more programing, it could be extended in future for robotics experiments. The XMP-1 uses low cost off-the-shelf standard hardware and no exotic tools beyond screwdriver, wire-cutters and pliers.

 

This post covers communication between the RPI and XMOS board using a serial peripheral interface (SPI) interface and how to construct up the XMP-1 and control it from a web browser.

The video here shows XMP-1 being taught a route; the first attempt at using it! It would benefit from a better user interface. XMP-1 can move quite fast, but I took it easy here on a low speed. On the right is the browser control, and at the bottom is the console output, just generating some keep-alive and status messages to see what's occurring.

 

This next video below shows the XMP-1 attempting to play back the route and causing suffering and pain along the way. My low-cost continuous rotation servos (which are being used to drive the wheels) were not very good, and XMP-1 has no sensors yet.

 

 

A bit more detail

This post is actually part 2 of some XMOS startKIT experiments. Part 1 contains the XMOS introduction, terminology, architecture and a quick getting started guide with example programs. If you're interested in the technology then it may help to follow part 1 first, so that this part 2 makes more sense. This part 2 is intended to construct a simple framework for high speed communications between the Raspberry Pi and the XMOS startKIT board. The framework should be general purpose enough to be able to use for many projects (robotics was not my intention). The XMP-1 is really just a by-product, in the desire to test out the Raspberry Pi to XMOS board communications. It is recorded here in case it is useful. (Note, there is also a part 3 entitled XMOS startKIT: XMOS and Raspberry Pi Oscilloscope XAE 1000 which reuses the SPI capability discussed is this post, and introduces how to use the analog to digital converter (ADC) that is present in the XMOS chip, and how to perform real-time graphics in a web browser).

xmp-photo.jpg


If you’re only interested in constructing and using XMP-1 then you can just take the code at the bottom of the post, compile and store to Flash (as described in part 1) on the XMOS startKIT board and the Raspberry Pi, and just follow the sections that describe XMP-1 hardware assembly, skipping all other content here. If you’re interested in controlling any hardware using the Raspberry Pi and a web browser then some of the code here can be reused. But, to get most out of the Raspberry Pi and XMOS startKIT combination the remainder information here may be useful if you’re new to the startKIT.

 

Solution Overview – Hardware and Software

Here is a photo of the completed XMP-1 being charged up. For outdoor use, I used a 802.11 hotspot type device (MiFi), running the browser on a mobile phone.

xmp-dev.jpg

 

The diagram below shows the approximate layout of the bits and pieces as viewed from the rear of XMP-1. You can see that it’s pretty basic – XMP-1 was just a quick experiment.

board-layout.png

 

The Raspberry Pi (RPI) is used to handle all network activity. It runs a small web server and most of the code is written in JavaScript on a Node.js platform. The RPI communicates motor control speeds (actually continuous rotation servos were used for XMP-1) over a serial interface (SPI) to the XMOS startKIT board. The XMOS startKIT is responsible for feeding pulse width modulation (PWM) signals to the motors.

The RPI is connected to the network using an 802.11 WiFi USB adapter.

The full wiring diagram is shown here. The hardware and construction is described later.

wiring.png

 

The diagram below shows the software that will be implemented on the RPI and on the startKIT. It looks a lot, but it isn’t and can be broken down into small parts which will be described further below. As mentioned the entire source code is at the bottom of this post so it could be used without any modification if desired.

solution-overview-software.png

 

In brief, the green block handles the web interaction and determines the speed and direction of the motors based on the user input. The green block provides a web page (index.html) to the user that incorporates the user interface. The xmos_servo program is a small bit of software written in C that translates the desired speed/direction into serial peripheral interface bytes of data that are sent to the startKIT. The startKIT software is divided into three parts that run simultaneously on separate XMOS cores. The spi_process converts the SPI signals into data that is stored in an array. The data_handler code inspects the array to decide what to do (the only conclusion it makes today is to manipulate the servos). The servo_handler process outputs a pulse stream to the servos, so that they can rotate at the desired speed. All these blocks are explained in more detail further below.

 

Serial Peripheral Interface (SPI)

SPI relies on four wires known as SS, SCLK, MISO and MOSI and an assignment of master and slave for the two devices involved in the communication. In the case of the RPI and XMOS board, the RPI is the master device and is responsible for generating the clock signal. The RPI transmits data on the MOSI wire, and received data on the MISO wire. This means that the SPI interface can transfer data in a bidirectional fashion at the same time. In practice if one-way data is required then either the MOSI or the MISO signal can be ignored depending on the direction of interest.

 

The oscilloscope screenshot here (individual signals and the automated SPI decode from a Tektronix MSO2024B oscilloscope) shows an example of SPI communication using the Raspberry Pi. SPI can be configured in a few ways; you can see in this example that three bytes of data were transferred from the master (RPI) to the slave (XMOS board) and that they were 0x02, 0x00 and 0x10, and either no data or 0x00, 0x00, 0x00 was transferred from the slave to the master simultaneously.

spi-comms-example2.png

The screenshot above shows a fairly slow SPI connection (32kHz clock rate) but it can be massively sped up as shown in the screenshot below:

high-speed-spi.png

The SS wire is a chip-select signal (active low). The RPI has two pins on it’s 26-way connector that could be used for SS; they are shown circled in blue in the diagram below, marked CE0 and CE1. This means that the RPI can talk to two SPI slave devices if desired. In this case, only one of the CE pins was used – I picked CE1.

rpi-marked.png

 

The pins circled in yellow above are the MOSI, MISO and SCLK pins on the Raspberry Pi. The pin circled in black is a 0V connection which would also be needed between the RPI and XMOS board.

 

Controlling Hobby Servo Motors

Hobby servo motors generate a movement based on an input signal. They usually rotate less than one full revolution. Usually a hobby servo will rotate within a range of about 180 degrees. The output shaft can be connected to (say) linkages to make wheels turn full left or full right (or anything in between) based on the input signal.

servo-typical.jpg

 

The diagram below shows the internals of a typical hobby servo (taken from this site). On the left (in blue) is a conventional DC motor. It is geared down a lot, and the final shaft can be seen on the right connected to a blue arm which could be connected to a wheel steering mechanism for example. Underneath the final shaft will be a potentiometer, and that provides feedback about the exact position of the final shaft. A hobby servo is therefore a closed loop system and can self-correct if the arm gets accidentally knocked away from the desired position.

Servo_Stripped.jpg

Hobby servos typically have three connections; 0V, 5V and Signal. The signal wire is a digital input to the servo and it requires a PWM signal. The size of the pulse width determines the angle that the shaft will move to. The PWM signal needs to repeat every 20 msec, and a pulse width of 1.5msec will result in the shaft moving to a centered position. A width of 1msec will move the servo fully in one direction, and a width of 2 msec will move the servo fully in the other direction (further below there will be some oscilloscope traces of servo control).

 

There is a type of modified servo known as a ‘continuous rotation’ servo. It is a modified servo where the potentiometer is removed along with any end-stops, and the circuitry is persuaded into thinking that the servo is still in the centered position. Sending PWM with a pulse width other than 1.5msec will make the mechanism rotate in the clockwise or anticlockwise direction at a speed that depends on the pulse width. The XMP-1 uses two continuous rotation hobby servos, one for each wheel. They are not an optimal way of obtaining controlled motion (XMP-2 will use DC brushed motors) since they are being used for a purpose different from the original intent for hobby servos, but they have the advantage that they can be controlled by a digital logic signal and they do not require any external H-bridge circuit.

 

Hobby servo wires can be color-coded differently depending on manufacturer. Usually the center wire is red, and it goes to +5V. The black or brown wire is 0V. The white or yellow wire is the PWM signal input.

 

Starting development - Connecting up the boards

In order to develop the software, the RPI and startKIT were connected up using a ribbon cable and IDC connector assembly - these can be assembled using a vice or purchased ready-made. For a self-assembled version it is worth buying an extra IDC connector for use as a debug connector at the center of the cable, to make life easier when probing signals with a multimeter or scope. Note that the left and right rows of pins on the debug connector swap around when done in the orientation shown in the photo below.

rpi-xmos-connected.jpg

The connector serving debug purposes close-up. I used these connectors:

debug-connector.jpg

With a RPI model A+ or B+, the connector is 40-way instead of 26-way, and due to lack of gap the 26-way ribbon cable will not fit the '+' models. One solution is shown below. Again the center connector is used for debugging purposes. This requires two 40-way connectors40-way connectors and 40-way ribbon cable40-way ribbon cable as well as the 26-way connector26-way connector.

xmos-startkit-rpi-plus-assembled.jpg

 

 

Implementing SPI (spi_process) on the XMOS startKIT

Using the XMOS development environment (xTIMEcomposer) was covered in part 1. The screenshots below show the Windows version of xTIMEcomposer, but the Linux version looks identical (and possibly the Mac version may look similar too).

Create a new project (File->New->xTIMEcomposer Project) and give it a name such as spi-test.

new-proj.png

 

A source code file will be created (spi-test.xc) which will be used to implement the main body of software.

There is a lot of pre-created code that is available for including, and it can be browsed by selecting the xSOFTip tab on the lower-left pane in xTIMEcomposer as shown in the screenshot below.

xsoftip.png

 

Select SPI Slave Function Library as shown in the screenshot above. When you do so, the Developer Column on the right side of xTIMEcomposer will update and show help information. Scroll down to obtain documentation links for the library.

developer-column.png

 

At this point you can right-click on the SPI Slave Function Library in the xSOFTip lab and import the library into the workspace. I’m no expert on xTIMEcomposer so I’m probably using it wrong here, but the source code and header file for the library appeared in a separate folder in the Project Explorer (shown circled in blue below):

proj-explorer.png

 

The files were required to be in the spi-test folder (so that they appear as shown circled in green above) so to achieve that I manually copied the spi_slave.h and spi_slave.xc files from module_spi_slave/src folder into the spi-test/src folder using Windows Explorer.

explorer-manual-move.png

 

The software uses the concept of ports to control output or to read input. There is a mapping between these logical ports and the physical mapping out to the pin on the chip. The mappings can be altered in certain combinations (See figure 3 in the Introduction to XS1 ports PDF document).

 

Input/Output ports on XMOS devices can be 1, 4, 8, 16 or 32-bit wide. When designing with the part, you may wish to allocate certain functions to 1-bit ports, or other functions to multi-bit ports, and so figure 3 will be very useful to determine which ports and pins to use.

 

With the SPI slave code now in the spi-test/src filder, this code was modified slightly. The library code makes an assumption that the ports that are being used for the SPI interface are all  1-bit ports, whereas the Raspberry Pi SPI SS pin (CE1) is connected to a 32-bit port on the XMOS board. Figure 8 from the startKIT Hardware Manual PDF document is shown below. In the center in green you can see the 2x13-way header that connects between the XMOS board and the Raspberry Pi. On the left and right in blue are the physical pin names on the chip (X0D0,, X0D11, etc). The pin highlighted values are the logical port numbers. P1A, P1D and so on are single-bit ports. P32A1 is the first binary digit of a 32-bit port.

xmos-port-pinout.png

 

Quite a few changes were made to the SPI library and the entire code is attached to the post, so only some snippets of code will be described here, there is no need to copy/paste, the full code attached at the end of this post can be used.

 

The SPI interface on the XMOS device is initialized as shown here. It is explained further below.

void spi_slave_init(spi_slave_interface &spi_if)
{


    int clk_start;
    set_clock_on(spi_if.blk);
    configure_clock_src(spi_if.blk, spi_if.sclk);
    configure_in_port(spi_if.mosi, spi_if.blk);
    configure_out_port(spi_if.miso, spi_if.blk, 0);
    start_clock(spi_if.blk);






    return;
}







 

As mentioned in the Part 1 post, I/O can be clocked in and out of the XMOS device at precise times. In the code above, the  set_clock_on function (defined in the XMOS xs1.h header file) is used to turn on one of the built-in clocking mechanisms in the XMOS chip. The diagram below (from the Introduction to XS1 Ports document) shows this mechanism in yellow. The configure_clock_src function is used to select an external clock (shown in blue in the diagram). It will be connected to the SCLK pin on the Raspberry Pi. The configure_in_port and configure_out_port functions are used to tie ports to the clocking mechanism. Both the MOSI and MISO signals (shown in green below) are configured to be tied to the clocking mechanism.

port-diag.png

 

The way serial data is handled on XMOS devices is really neat. The code here is explained further below. First, a structure is used to contain details about the ports that are desired to be used as the SPI interface.

typedef struct spi_slave_interface
{
    clock blk;
    in port ss;
    in buffered port:8 mosi;
    out buffered port:8 miso;
    in port sclk;
} spi_slave_interface;







 

The interesting lines above are the ones that refer to port variables mosi and miso. They have been declared as type port:8. If the variables are assigned 1-bit port addresses, then the XMOS device will automatically de-serialize the 1-wire stream of bits into 8-bit values.

It makes the rest of the SPI code really simple. Here is the code that manages SPI data input from the Raspberry Pi:

void spi_slave_in_buffer(spi_slave_interface &spi_if, unsigned char buffer[], int num_bytes)
{
    unsigned int data;
    unsigned int vlen=0;


    clearbuf(spi_if.miso);
    clearbuf(spi_if.mosi);


    for (int i = 0; i < num_bytes; i++)
    {
        spi_if.mosi :> data;
        data=data<<24;
        buffer[i]=bitrev(data);
        if (i==2)
        {
            vlen=(((unsigned int)buffer[1])<<8) | (unsigned int)buffer[2];
            if (vlen==0)
                break;
        }
        if (i >= vlen+2)
        {
            break;
        }
    }
}







 

In the code above, you can see that there is a for loop, and within the loop the line spi_if.mosi :> data; is used to read 8 bits of information on the MOSI line into the variable called data.

 

The next two lines are used to flip the bits around within the byte and then the data is stored in a buffer array.

 

The next few lines need some explanation; they are related to the desired protocol. It was intended to create some general-purpose code that could be used for many things, not just XMP-1. If the Raspberry Pi sends data to the XMOS startKIT board, the XMOS board needs to know how many bytes of data to expect. This could be hard coded but it would be inflexible.

 

It was decided to use a very simple ‘tag (or type), length, value’ (TLV) protocol. The first byte that the Raspberry Pi must transmit is a tag or identifier in the range 0-255 (i.e. one byte). It is up to the user to decide what the values represent. For example, a value of 1 could mean “set motor speed” and a value of 2 could mean “set headlight brightness intensity”. The second two bytes are a 16-bit value that indicate how many value (i.e. data) bytes are to follow. I decided to limit this to 4kbyte (4096 bytes) which should meet many use-cases but the actual value can be changed by adjusting a BUFLEN definition in the code.

 

Therefore the minimum number of bytes sent on the SPI interface are three (tag, and a length of 0x0000) and the maximum are 4099 which is a tag and a length of 0x1000 (this is 4096 in hexadecimal) and 4096 data bytes.

 

The protocol was refined slightly, so that an odd tag number means that the Raspberry Pi expects a response back in the following SPI communication that it initiates after the current TLV stream is complete, and an even tag number means that the Raspberry Pi expects no response back.

 

This is a very basic protocol but it should meet many usual requirements. It is also explained in the table below where the blue number is the SPI byte index into the receiving 4099-byte buffer.

tlv-scheme.png

 

Going back to the earlier code snippet it can be seen that the next few lines check the buffer[1] and buffer[2] contents on the fly while the SPI data is being received. The contents are expected to be the length as seen in the diagram above (see blue buffer index). As soon as the code has determined the remainder length, it will accept exactly that number of Data bytes, and then the routine exits.

 

That covers SPI input to the XMOS board on the MOSI line. SPI output from the XMOS device on the MISO line operates in a similar manner, checking the the length simultaneously on the MOSI line on the fly again, so that the function can exit as soon as the requested number of bytes has been transferred.

 

Inter-Process Communication

Now that SPI was figured out and a protocol had been implemented to exchange variable length data in either direction up to 4096 bytes long, some consideration was given to the main body of the program. It was clear that an XMOS core would be dedicated to handling the SPI task, but the rest of the code may need to reside in one or more additional XMOS cores.

 

In part 1, it was described how tasks run in parallel on different XMOS cores, and how the tasks can communicate to each other by pushing values into channels. There is another way of communicating between cores and it uses the concept of “transactions via interfaces” rather than channels. It is more flexible because you can send multiple variables of different types from one XMOS core to another. The transaction types are defined much like a C function prototype. This all becomes much clearer by looking at an example.

 

For instance, if an application had a task that controlled a display, then a sending task may want to turn the display on or off, or it may want to plot a pixel. The interface definition for the communication between the two XMOS cores could look something like this:

interface program_display
{
    void backlight(int state, int color) ; // transaction type 1
    void plot(int x, int y, int color); // transaction type 2
};







 

Interface communication is unidirectional, so if the display wanted to send information such as (say) the touchscreen state, then another interface would need to be used in the other direction. From this it is clear that interfaces have a client and server end. The diagram here shows two XMOS cores (in purple), two interfaces (in gray) and the first interface (called program_display) allows two different types of transactions to occur (in blue) across the program_display interface.

interface-comms.png

The great thing about using interfaces and transaction types is that, much like C function prototypes, you can have return values and you can pass references to variables, so that even though the communication is always initiated by the client end of the interface, data transfer can occur both-ways. Another very interesting feature not shown on the diagram is the ability for the server end to be able to send a ‘notification’ to the client end. This can be a signal to the client to issue a transaction in the usual manner, to perhaps retrieve some data. This feature will be used in the XMP-1 code. So, more information on exactly how to code the interfaces and send data and notifications will be explained further below.

 

Designing the IPC architecture to handle SPI content

The SPI interface handling has already been described. Now the content of the SPI messages needs to be presented to a task in a useful manner for subsequent processing. Armed with the knowledge about interfaces and transactions, it was possible to begin allocating functionality to separate XMOS cores and designing the inter-process communication to get to a general-purpose framework that would allow useful message content to be sent from the RPI to the XMOS board and vice-versa, and be processed.

 

The diagram here shows what was developed (a similar diagram as before, except now there is a time sequence from top to bottom).

arch1.png

When the Raspberry Pi desires to send a message to the XMOS board, the RPI will construct up the message into the TLV format described earlier. The information is then clocked out on the MOSI signal wire (shown in green at the top of the diagram above). Simultaneously the XMOS device needs to send something back, but since there is no information yet to send back, the MISO line can contain garbage or all zero values as shown in pink. The spi_process function will collect up the message into a buffer (an array of unsigned char) and then it will initiate a transaction to a separate data_handler XMOS core. The data_handler is responsible for processing the contents of the message and optionally sending back information to the spi_process XMOS core, so that any subsequent SPI exchange can send useful data back to the Raspberry Pi instead of garbage values.

 

The data could be sent between spi_process and data_handler by making a copy of the buffer. However instead it is possible to just pass a pointer to the buffer memory. One way this can be done is to ‘move’ control of the pointer and buffer memory locations  from spi_process to data_handler. Once data_handler is done with the message inspection, it can move control back to spi_process using the return variable that is possible to use in transactions. This is why the diagram above has a transaction called array_data with a parameter defined as a moveable pointer and a return value defined as a moveable pointer too. This way, only one XMOS core has access to the buffer memory at any one time.

 

These are the interfaces that are used:

interface to_rpi
{
    void code(unsigned char c);
};


interface from_rpi
{
    unsigned char* movable array_data(unsigned char* movable bufp);
};







 

The spi_handler code allocates space for a buffer, and then passes control of the buffer to the data_handler code using the line buf=c.array_data(move(buf)) shown in the code here:

void
spi_process(interface to_rpi server s, interface from_rpi client c)
{
  unsigned char storage[4099];
  unsigned char* movable buf=storage;
  ...
  buf=c.array_data(move(buf));
  ...
  select
  {
    case s.code(unsigned char c):
      if (c==SEND)
      {
        spi_slave_out_buffer(spi_sif, buf, 4099);
      }
      break;
  }
}







 

The data_handler code obtains control of the buffer and then if any response is desired to be sent to the RPI on a subsequent SPI transaction, the buffer is populated with a response. Finally control of the buffer is passed back to the spi_handler process.

void
data_handler(interface to_rpi client c, interface from_rpi server s)
{
  select
  {
      case s.array_data(unsigned char* movable vp) -> unsigned char* movable vq:
         // vq contains the data from SPI. We can do whatever we like with it here.
         // Any response is constructed up here too:
         vq[0]=0x22; // tag
         vq[1]=0x00; // length
         vq[2]=0x00; // length
         vq=move(vp);  // pass the pointer control back to spi_process
         tosend=1;
         break;
     }
  if (tosend)
  {
    c.code(SEND);  // send a code to spi_process so that it is aware there is data to send to RPI
  }
}







 

Earlier it was mentioned that if an odd tag value was sent by the RPI then this would be an indication that the RPI expected a response message from the XMOS startKIT board on the subsequent SPI exchange. This is implemented by both the spi_process and data_handler making a note that a return message is expected if the first byte received is an odd value. Once data_handler has finished constructing the return message in the buffer memory it moves the buffer pointer back to the spi_process XMOS core and also sends a code transaction which could contain a message such as “ready to send”. The spi_process XMOS core is now ready for any subsequent SPI exchange. If the data_process doesn’t want to send any message back to the Raspberry Pi (for example if the tag was even valued) then the code transaction is not sent (or a different code could be sent such as “not ready to send”).

 

In the graphic diagram earlier you can see that the subsequent SPI exchange did transmit data back to the Raspberry Pi on the MISO wire.

 

To summarize, the spi_process and data_process present a fairly general-purpose capability to exchange data bidirectionally between the RPI and XMOS board.

 

Implementing PWM (servo_handler) on the startKIT

To test out the general purpose architecture, it was decided to use it to control many devices. The devices ended up being hobby servos because they require very little electrical interfacing effort - no H-bridge or transistor driver is needed – and the servo input wire can be directly connected to an XMOS output pin. I didn’t have many servos, so although the code implements 8 servo control, only two were used for XMP-1.

 

The code could be modified to provide DC motor control too (with a suitable external H-bridge circuit).

 

It was decided to use a single XMOS core to handle the eight servos. The diagram below shows the total of three XMOS processes used in the solution. The new addition is the servo_handler task which is shown on the right. This task has an array that stores the current servo values. As soon as the task starts up, the values are initialized to a centered value (or standstill for a continuous rotation servo) and then every microsecond the task wakes up to check if the servo PWM signal needs adjustment.  If it does then the servo port output is toggled. After 20msec the process repeats.

arch-servos.png

As before, the Raspberry Pi will send a TLV format message to the startKIT board. This time the tag will be an even number, so no response is expected. 16 value (data) bytes will be sent, two per servo. The buffer will be moved to the data_handler task as before. It will now check for a tag number 2, and if it matches then it sends a notification (shown as a dashed blue arrow in the diagram above) called data_ready to the servo_handler task, to make it aware that new servo setting values are available. When ready, the servo_handler task will move it’s servo settings pointer to the data_handler process for it to populate the servo settings to new values and move the pointer back to the servo_handler process.

 

This is the interface definition to achieve the notification and transfer of data:

interface servo_data
{
    [[notification]] slave void data_ready(void);
    [[clears_notification]] unsigned int* movable get_data(unsigned int* movable servop);
};







 

The data_handler XMOS core contains this snippet of code which checks to see if the command from the RPI relates to servo control (by checking the first tag byte) and then storing the servo data locally until the servo_handler requests it:

void
data_handler(interface to_rpi client c,
             interface from_rpi server s,
             interface servo_data server ss)
{
  unsigned int servo_request[8];
  select
  {
      case s.array_data(unsigned char* movable vp) -> unsigned char* movable vq:
        if (vp[0]==0x02)  // servo update request
        {
            idx=3;
            for (i=0; i<8; i++)
            {
                servo_request[i]=(((unsigned int)vp[idx])<<8) | ((unsigned int)vp[idx+1]);
                idx=idx+2;
            }
            ss.data_ready(); // send notification to servo_handler
        }
        break;
      case ss.get_data(unsigned int* movable servop) -> unsigned int* movable servoq:
           for (i=0; i<8; i++)                                                
           {                                                                  
               servop[i]=servo_request[i];                                    
           }                                                                  
           servoq=move(servop);                                               
           break;                                                             
  } // end select
}







 

The servo_handler receives the notification and retrieves the data by temporarily passing control of local storage called servo_width to the data_handler to populate. It is achieved using the ptr=cc.get_data(move(ptr)) line below:        

void                                                                                                   
servo_handler(interface servo_data client cc)
{
  unsigned int servo_width[8];
  unsigned int* movable ptr=servo_width;


  select
  {
    case cc.data_ready():
      ptr=cc.get_data(move(ptr));              
      break;
  }
} 







 

The actual PWM output was achieved in a simplistic manner using a 1 microsecond timer. Since servos only need up to a 2msec pulse every 20msec, the XMOS core can be put to sleep for a large portion of the time.

select
{
    case t when timerafter(time+wait) :> time: // 1*1E2 is 1usec
        for (i=0; i<8; i++)
        {
            if (period==0)
            {
                servo_port[i] <: 1;
                wait=1*1E2;
            }
            if (period==swp[i])
            {
                servo_port[i] <: 0;
            }
        }
        period++;
        if (period>3000) // 3msec
        {
            period=0;
            wait=17*1E5; // 17 msec
        }
        break;
}







 

The oscilloscope screenshot below shows the signals to control four servos, all in the centered position. The pulse width is 1.5 msec here and the period is 20 msec.

servo-centered.png

By sending different commands to the XMOS startKIT, the pulse widths can be changed as shown below (the screenshot below has a different time scale, to show the pulse width in more detail).

servo-various.png

Raspberry Pi code: Handling the SPI interface

The XMOS source code has been described. On the Raspberry Pi, there are two programs that run; a small program called xmos_servo which handles the SPI interaction, and the web/application server running on Node.js (see the solution overview near the beginning of the post to recall these bits of functionality).

 

There xmos_servo code was based on existing code called spidev.c which is a test program for SPI. It was modified to accept servo pulse width parameters on the command line.

 

To use the code, the SPI interface on the RPI needs to be enabled. This is done by typing sudo raspi-config on the RPI command line, selecting Advanced -> SPI settings and then ensuring Enabled is selected. Then, exit out by selecting Finish.

 

Issue sudo reboot (this may or may not be necessary) and then you should see in the /dev folder:

spidev0.0
spidev0.1







 

From the home folder (/home/pi) location create a folder called (say) development, and in there create a folder called something like xmos:

mkdir –p development/xmos
cd development/xmos







 

Place the xmos.c file that is in the zip file at the bottom of this post into that folder, and compile the code:

gcc –o xmos_servo xmos.c







 

You can now run it and control the servos from the command line using this syntax as an example:

./xmos_servo 1500 1500







 

1500 is the desired pulse width in microseconds. Anything between about 500 and 2500 may be useful depending on the actual servo. Since the servos are mounted on opposite sides of XMP-1, the two servos require a value higher than 1500 and a value lower than 1500 for them to rotate in the same direction.

 

Low cost servos will need some trimming in the software to set the center point where no rotation will occur. It should be 1500, but for the servos that I used it was about 1460 microseconds.

 

Raspberry Pi web server and application software

Node.js is something worth experimenting with, because it speeds up application development tremendously. It allows you to write applications in JavaScript. Here the entire web server and application is written in JavaScript. It means that no Apache or Lighttpd web server needs installation and configuration.

 

In a post around Christmas time the procedure to install Node.js was described. Here, a similar exercise is undertaken (some of it is cut-and-pasted here) but with a more recent version of Node.js.

 

Issue the following commands from the /home/pi folder:

cd /home/pi
mkdir mytemp
cd mytemp
wget http://nodejs.org/dist/v0.10.26/node-v0.10.26-linux-arm-pi.tar.gz
tar xzvf node-v0.10.26-linux-arm-pi.tar.gz
sudo mkdir /opt/node
sudo cp -r node-v0.10.26-linux-arm-pi/* /opt/node







 

The above will result in the node executable being placed at /opt/node/bin being installed.

The /etc/profile file needs two lines added before the line that says ‘export PATH’. To do this, type

sudo vi /etc/profile







 

(assuming you know how to use vi; otherwise use an alternate editor). These are the two lines to be added:

NODE_JS_HOME="/opt/node"
PATH="$PATH:$NODE_JS_HOME/bin"







 

Then, reboot the RPI:

sudo reboot







 

Once it comes back alive, the next step is to install socket.IO:

cd ~/development/xmos
npm install socket.io







 

The above command will take about 5 minutes to complete.

 

The HTML file that will be served to the user is in a file called index.html. It has two parts. The first part (actually in the second half of the file) contains lots of buttons, for example here the forward speed buttons are implemented:

<p>
  <label for="id_button_turn">Forward</label>
  <input type="submit" name="id_button_fwd_high" id="id_button_fwd_high" value="High"  onclick="fwd_click(3)">
  <input type="submit" name="id_button_fwd_med" id="id_button_fwd_med" value="Med"  onclick="fwd_click(2)">
  <input type="submit" name="id_button_fwd" id="id_button_fwd" value="Low"  onclick="fwd_click(1)">
  <input type="submit" name="id_button_stop1" id="id_button_stop1" value="Stop"  onclick="stop_click()">
</p>







 

The second part (near the top of the file) contains JavaScript code that sends the button click to the Node.js web server that will run on the RPI. It is using Socket.IO to send data:

  function fwd_click(i){
  var statustext = document.createTextNode("Status: Setting FWD... ");
  clear_stat();
  stat_div.appendChild(statustext);
  socket.emit('action', { command: 'fwd'+i });
  }







 

The code also implements a return status bar, and the entire file is in the attached zip file.

browser2.jpg

 

The remainder of the software on the RPI is coded in JavaScript in a file called index.js.

These few lines of code implement a simple web browser:

var app = require('http').createServer(handler)

// HTML handler
function handler (req, res)
{
  console.log('url is '+req.url.substr(1));
  reqfile=req.url.substr(1);
  if (reqfile != "xmp-logo.png")
  {
  reqfile="index.html"; // only allow this file for now
  }
  fs.readFile(progpath+reqfile,
  function (err, data)
  {
    if (err)
    {
      res.writeHead(500);
      return res.end('Error loading index.html');
    }
    res.writeHead(200);
    res.end(data);
  });
}







 

The snippet of code that allows the JavaScript program to execute the xmos_servo program and pass the servo parameters is shown here:

var progpath='/home/pi/development/xmos/';
prog=child.exec(progpath+'xmos_servo '+value[0]+' '+value[1]), function (error, stdout, stderr){};
  prog.on('exit', function(code)
  {
  console.log('app complete');
  });
The Socket.IO connection is handled using this code:
// Socket.IO comms handling
// A bit over-the-top but we use some handshaking here
// We advertise message 'status stat:idle' to the browser once,
// and then wait for message 'action command:xyz'
// We handle the action xyz and then emit the message 'status stat:done'
io.sockets.on('connection', function (socket)
{
  socket.emit('status', {stat: 'idle'});
  socket.on('action', function (data)
  {
    console.log(data);
    cmd=data.command;
    console.log(cmd);
    // perform the desired action based on 'command':
    ret=handleCommand(cmd);
    socket.emit('status', {stat: ret});
  }); // end of socket.on('action', function (data)
}); // end of io.sockets.on('connection', function (socket)







 

The remainder of code inside the index.js file implements the logic that maps the command from the user (via Socket.IO) into values for the servos. Any trimming of values for low cost servos is done in this code using hard-coded values.

 

Assembling XMP-1

XMP-1 was assembled literally using string. It couldn't get more simplistic :-) Ordinary string may loosen, so lacing cord was used (it has a non-stretchy core, and a soft outer coating that doesn’t loosen easily. The base of XMP-1 was a piece of pre-cut 100x100mm perforated sheet steel from ebay, there are lots of sellers for this. In H.G. Wells fashion all the messy mechanics/charging/power stuff was down below on the underside, and the RPI/XMOS startKIT were on top.

 

Here the servos were tied to the base, and the front ball/caster (from Tamiya) was mounted with some screws and M3 hex spacers and bolts/nuts to get the height correct. With lacing cord, the servos are extremely secure and don’t move.

xmp-top-initial.jpg

 

The photo below shows the underside view. The wheels were from Pololu (they sell two kinds in this range, one does not fit on standard servos – this one does).

xmp-underside-initial.jpg

 

Below is a photo of the underside with a few more bits added. I just used whatever charger/DC-DC converter and battery that I had. I used a LiPo Rider Pro board (blue board in this photo) which contains the charger and 5V DC-DC output converter combined on one board. This supplied sufficient power to drive the two servos and the XMOS board. The LiPo cell was from Farnell (shown in the center of the photo, in-between the servos). The cell is a high cost part in this build but it is not safe to trust unbranded LiPo batteries or batteries from suppliers who do not indicate where the battery came from, especially for this type of project. I think it will give many years of good service long after XMP-1 has been disassembled. If a different battery is used, ensure it is not much higher capacity (this is a lot of energy), and that it has a built-in protection circuit. Even so, I would not consider leaving a project charging unattended. In a similar vein, it would be safer to use a plastic base (and drill holes, or have them laser cut as an example) to minimise risk of a short to the chassis especially from sharp edges.

xmp-underside-partial.jpg

 

The RPI is powered from a smaller, separate LiPo battery – this is because under load, the servos may consume enough power to cause the RPI to reset. By far the easiest thing to do is just run it from a separate supply.

 

The photo below shows the following things circled in different colors:

Red: Tamiya ball/caster

Green: 5V output DC-DC converter for RPI from ebay (the exact model I used is unavailable but there are plenty of others)

Yellow: Charger circuit for RPI LiPo battery from Olimex (they also have suitable batteries for powering the RPI, such as this one)

Blue: A small stripboard to serve as the supply junction point for the two servos and the 5V output from the LiPo Rider Pro board (which can be seen in blue in the background).

underside-castor.jpg

 

Here is the final result:

xmp-rpi-side-zoomed.jpg

 

Summary

It is hoped that some bits of this post may be useful. As can be seen, it is fairly straightforward to connect up the Raspberry Pi to the XMOS startKIT and begin making projects with high-speed, low-latency timing. Unlike other solutions, the XMOS startKIT is extremely low priced, and has incredible timing performance – absolutely ideal for robotics projects. XMP-2 will replace low-cost servo motors with brushed DC motors in a complete redesign which will need additional tools. XMP-1 however provided a lot of fun and a good opportunity to learn XMOS, with a very short assembly time (a few hours).

 

The SPI code can be re-used for any high-speed input/output that may be needed for RPI/XMOS combined projects.

 

For projects that require web based control, Node.js is highly worth considering. It runs quickly on the RPI, and needs no configuration (unlike Apache) and allows applications to be written quickly in a small amount of code.

 

 

Code is available here.

shabaz

Sleepy Pi Overview

Posted by shabaz Top Member Dec 14, 2013

Introduction

The Sleepy Pi is a board produced not a million miles from my home town, and it is designed to extend the Raspberry Pi (RPI) capabilities. After having examined it, the conclusion is that the board is fantastic with a rich set of functionality and extremely well-designed, and it will provide tremendous value for projects with the types of requirements listed below.

L1060360.jpg

This board should interest people with any of these requirements:

1.    The ability to run the RPI from a battery

2.    The ability to run the RPI intermittently (based on events or time), perhaps over days/months from a remote location

3.    Interface to hardware and run microcontroller code

4.    Use existing Arduino compatible boards

5.    The ability to keep time without a time server on the Internet

It opens up some unique opportunities.  For example you could shut down the RPI, collect data using the far lower power  in-built microcontroller on the Sleepy Pi, and then periodically wake up the RPI and send the data to a server. The RPI could run for days/weeks/months like this at a remote location.

 

Main Features

The main features are:

1.    Provide battery backed up clock (it has a socket for a watch type cell)

2.    Provide efficient, regulated power to the RPI (there is a built-in DC-DC converter and a DC barrel socket) – or use your existing power supply (there is a USB socket for that)

3.    Allow the RPI to be put to a ‘deep sleep’ (power off) and awakened at certain defined times or when a particular event (analog or digital input) occurs

4.    Allows external hardware to receive a switched power supply, so that it can be put to sleep too

You can see the RTC back-up battery socket on the underside (battery not supplied due to postal restrictions - a CR1632 cell is needed for enabling that capability):

L1060361.jpg

The diagram here is from the Sleepy Pi website:

sleepy-pi-block-diag.jpg

This photo shows the mapping of where bits of functionality are located on the board:

L1060362-annotated.jpg

Owing to its design, it has some very attractive additional advantages:

1.    Arduino compatible boards can be plugged in on top, for extending usefulness

2.    There is an on-board Atmel AVR microcontroller – on of the world’s most popular microcontrollers – which allows for some relatively high speed interfacing to hardware without the varying latency that Linux would incur

3.    Decent area for prototyping – saves an additional board

4.    Built-in ADC (in the AVR chip) for connecting to analog sensors (two 10-bit analog channels)

5.    Additional 'peripherals' available inside the AVR chip, such as PWM for controlling analog devices or for light dimming/motor control (requires additional circuitry)

 

Design Overview

There are many bad and good boards out there, this one falls in the extremely good category.

Hardware Design

The design is really nice – the list of good points seems endless: sensibly, it is a rectangular board without strange cut-outs (which save little space and wouldn’t allow the PCB to fit many cases anyway) so it allows for a usable prototyping area which is really nice. There is space for screw terminals and Arduino headers. All connections are well labelled.

Many connectors are supplied, so you can use the board as you wish. The existing RPI 26-pin connector is not totally consumed and lost; there is an inline header so that additional boards could in theory become part of the sandwich.

The board is securely fastened to the RPI using hex spacers (you will need a 2.5mm hex driver for the supplied bolts). As a design suggestion, perhaps some more holes on the Sleepy Pi would be good, so that it can be bolted into a case. Extra holes may be hard to implement because the board is so packed. A good workaround is to use hex spacers with male thread on one end, so it is a very minor point.

It is nice that decent hex bolts are supplied (this controls the amount of space the head consumes around the board) and insulating washers for the paranoid (like me). I’m really struggling to find a bad point about the Sleepy Pi.

I’d suggest one additional hole, so that it can finally fix the RPI weakness of two holes, since a total of three holes will allow it to firmly be fixed to a surface.

As another suggestion, perhaps a couple of very small holes near the battery, so that it can be tied down if desired and not vibrate/drop out (people may use the Sleepy Pi in some extreme conditions), especially since it is on the underside of the board.

As far as I can tell, the board does not foul up any existing connector on the RPI, including the camera connector.

AVR Microcontroller (Arduino)

In normal (expected) use, no additional hardware is needed and you will be able to run Arduino code directly on the Sleepy Pi.

If required, there is a 6-pin Atmel AVR header for an external programmer. This will allow you to run code written without Arduino support too.

Note that as far as I can tell, the board could in theory even be used independently of the RPI. So, if you happen to need an AVR microcontroller and RTC and DC-DC supply to power your electronic circuit, then this board could be useful for that purpose too.

If you don’t wish to go Arduino-mode and wish to program the AVR yourself, then a programmer is available for under £20($30) (Olimex AVR-ISP-MK2) from Farnell/Newark and it will plug in directly to the Sleepy Pi. I’ve not used it, but it is worth a try – since the Atmel version AVR-ISP 2 is a little tricky sometimes to set up with Windows 7.

The AVR is a great introduction to microcontrollers and has so many uses and existing code snippets available all over the Internet.

Circuit Design

Looking at the schematic, it all looks very nice – decent protection on the power inputs, very good power control using MOSFETs (with protection too), unlike some RPI power control designs which use relays, and the design looks an extremely good quality (a few tantalum, and mainly ceramic caps everywhere as expected for this type of design) and decent modern component selection everywhere.

This is the type of design someone would do for themselves and be proud of the result, rather than a design intended for sale at a reduced price point with a compromised quality.

In the spirit of open source, the schematic is available and any code is on Github. This is a really important because many RPI boards are intended for educational use yet the creators hide the design (maybe they should be named and shamed!) because so much can be learned from looking at the design detail.

Prototyping Area

The prototyping area is of the round isolated rings variety, which is amongst the most useful – it can be used for through-hole parts but also for soldering up surface-mount devices sometimes and joined with thin bare wire.

 

Summary

It is no surprise if you’ve read the above - this is an impressive board. It is well designed and packed with features. The cost may seem high (£36.99 including VAT) but it does what you would previously have needed several boards to do, and good parts cost money - the design is of a very high quality.

Introduction

This was a fun project to try to make some flashing lights. Of course, it needed to be a bit more complex than that so a Raspberry Pi was used for Internet connectivity, and some analog circuitry was used to generate multiple PWM outputs to drive strings of lamps. Everything can be dimmed or particular patterns selected from any web browser. For a holiday look, the lamps were enclosed in star-shaped laser-cut acrylic. All the steps are detailed here if you wish to build something similar.

whole-project-working.jpg

The controller board was built in two evenings after work, and the strings of lamps can take a few hours to assemble; so this could be a weekend project.

Even if you’ve already have your holiday lights arranged by now, this post may be useful for the following information:

•    Using 555 timers

•    Controlling a DAC using the Raspberry Pi

•    Controlling hardware using MOSFETs

The source code is also useful if you have other requirements for controlling or retrieving status information from software or hardware using a web browser.

 

The project uses low voltage lighting for safety and hardware PWM to greatly simplify the software. The software is simplified further by utilizing JavaScript as the main programming language; the entire project occupies just three small files.

 

The plastic parts are possible from most laser cutting services; however if you contact Problemchild he has the design files and can supply a very good quote for these shapes in various translucent colors. The plastic shapes in this post used John’s laser cutting service.

Here is a video of it in action running one of the patterns (it can handle multiple patterns all controllable via the web browser including pattern speed):

 

This is the actual controller board (it was stacked under the Raspberry Pi in the earlier photo):

whole-project-working-unstacked.jpg

 

Solution Overview

The diagram here shows how it all works. The user controls the whole thing from a web browser. The controller board powers four channels of lighting. The light strings can total 12V or 24V for flexibility and can be powered with a small mains adapter. These low voltages mean that the project is safe.

simplified-overview.png

The project here used 5V lamps and chained five of them in series for each channel, i.e. totalling 20 lamps run from 24V. It is also possible to drive lamps in parallel if desired, if longer lengths of lighting need to be driven.

 

The project can be split into two halves; Part of it is software, and part of it is in hardware. You can skip the design descriptions below and go straight to the build if desired.

 

Software Design Overview

The software needs to do a few things; serve up and handle web page interaction, implement a lighting patterns using some sort of timer for animation, and to drive some of the pins on the RPI (general purpose I/O pins) to control the hardware which will drive the lights.

 

There are many ways to achieve these tasks; in this case, a software platform called Node.js was predominantly used (thanks fustini ). It allows most of the software to be written in JavaScript, and also eliminates the need to install a heavy web server such as Apache, because a lightweight web server is available for Node.js. It reduces the need to use another programming language; the code that will be written to run on the RPI will be in the same language as the software that will run in the web browser as coded in the HTML file.

 

Note that a very tiny piece of software is written in C; that bit of code is the interface to GPIO.

 

To summarise, just three files are needed; the Node.js program (written in JavaScript), the HTML file and the C program that will write to the controller board over GPIO. These three files are attached in the zip file at the end of this post.

 

The small C program is called ‘dac’ (predictably it is used to control a DAC on the controller board which adjusts the channel brightness as will be seen later). The program can be executed from the command line using:

./dac <chan> <value>
    

where the first parameter corresponds to a channel between 1 and 4, and the second parameter sets the brightness value between 0 and 255. In our case, the Node.js program software directly calls the dac program.

 

The diagram here shows a graphic view of the software components that will be running inside the RPI. The three software files are shown in green (index.js JavaScript file), blue (index.html file) and red (the dac.c program). It is all fairly self-explanatory if you view and compare it with the code.

software-overview.png

Hardware Overview

There are many ways to generate PWM; the design here uses a 555 timer chip to create a fixed-frequency sawtooth waveform that is continually compared to an adjustable voltage from a DAC. Whenever this DAC adjustable voltage exceeds the sawtooth level, the string of lamps is switched on using a MOSFET. By using quad DAC and quad comparator ICs, the circuit allows for 4 channels to be independently controlled (just one channel is shown in the diagram below for simplicity).

hardware-overview.png

 

Building the Circuit

The circuit can be built in 4 portions (5V regulator, sawtooth generator, comparators+MOSFETs and DAC) with each part tested before moving to the next part. No special equipment is needed to test; a multimeter and a pair of headphones are sufficient.

 

The circuit was created on prototyping board of the circular ring variety (sometimes known as perfboard), but stripboard could be used too if preferred. With the circular ring type board, the components are soldered in position and then very thin bare wire can be used to make traces on the underside (other ways are possible too).

 

The photo below shows the mapping of the bits of circuit;

Blue: regulator circuit

Green: sawtooth generator

Red: comparator

Purple: MOSFET outputs

Yellow: DAC

board-highlighted-closeup.jpg

 

Physical Layout Diagram

The entire layout is shown here and can be used as-is, or if you want the boards to stack then a minor change is that a couple of parts need to move slightly to accommodate the screw holes that need to be created in the prototyping board.

board-layout-guideline.png

As mentioned, most of the wiring occurs on the underside of the board using thin bare wire. Note that capacitors C6 and C9 are soldered on the underside too, to keep wire lengths short. Each portion of the build is described in detail below but refer to the physical layout diagram above as you are building each portion.

 

The first step is to drill holes if you desire the boards to stack:

board-holes-med.jpg

At this stage it is worth attempting to assemble the RPI on top to ensure that the holes are in the correct position before proceeding further.

 

5V Supply

Most of the circuit operates from 5V, but the lamps require a higher voltage since they will be chained together. A 78L05 voltage regulator circuit was built, and then tested with a multimeter before proceeding further. The 78xx series regulators are extremely common and used in a lot of projects. The ‘L’ variant is used for low power applications. The DC socket J1 is available in thin and fat center pin variants and usually the correct one is needed to match the power supply. To save headache, use the recommended socket which has a compressible diameter center pin that can handle both thicknesses of the mating plug.

regulator-circuit2.png

Once you have built up the regulator circuit, check with a multimeter on the unpowered circuit to ensure there are no obvious faults like a short circuit between the +24V, +5V and 0V wires. Once this is done, power it up and confirm that you can successfully see the 5V output.

 

Sawtooth Generator

The sawtooth generator consists of a 555 oscillator chip combined with a single transistor constant current source. The sawtooth waveform is taken from the capacitor, instead of pin 3 of the 555. The 555 is an extremely popular chip – see here for fifty more ideas.

sawtooth-circuit2.png

With the two capacitors C3 and C4 as shown in the circuit diagram, the frequency of oscillation is quite low (a few kHz) so that it is possible to test the circuit easily without requiring an oscilloscope, before proceeding further.

 

To test the circuit, connect up a low cost pair of headphones to pin 3 of the 555 and to ground in series with a small capacitor (100nF is fine). You should hear a high-pitched tone. If this is successful then the circuit so far works well. The test is complete! Unsolder or cut out the C4 capacitor to increase the frequency to a usable level for the project. The frequency will now be approximately 15kHz.

The diagram here shows the generated waveform.

sawtooth-annotated.png

PWM Generator and Output Circuit

The PWM signal is created using a comparator chip. As the name suggests, such a device can compare two inputs and the output becomes high or low depending on which input is higher than the other. By supplying a fixed frequency sawtooth as one input to the comparator, it is possible to generate any pulse width (up to the period of the sawtooth) by adjusting a voltage level on the other input of the comparator. If you want to see this as an animation, click here (java needs to be installed).

You will see a screen similar to the one below. By adjusting the slider at the bottom-right, the PWM level can be adjusted and is reflected in the animated waveform displays. Note that this simulator is useful for testing out other circuits too.

falstad-sim.png

The actual circuit is shown below. The output of the comparator is known as ‘open drain’ which allows it to be connected up to a higher voltage. Five lamps are connected in series (each one is rated for 5V), which is ideal for powering from a small 24V mains adapter. The circuit is repeated four times so that multiple channels of lights can be controlled. Refer to the table to the left of the circuit below for the pinout for the LM2901 chip which contains 4 comparators inside.

pwm-and-output-circuit2.png

Once this part of the circuit is assembled, it is possible to test by applying a controlling voltage (using a variable resistor) to pin 7,5, 9 or 11 of the LM2901 IC and observe the dimming action of the lights. If the lights have not been assembled, you can use a single LED in series with a 2.2k resistor.

 

The traces below show the signals probing at various points in the circuit. As the controlling voltage is varied, the width of the blue and purple pulses will change.pwm-waveforms-annotated.png

DAC Circuit

The final part of the circuit is the quad DAC implementation that will interface between the Raspberry Pi and the comparators. A reference voltage of about 3.8V is created using resistors R14 and R15 (potential divider circuit). This provides a fraction less than 8 bits of resolution for the lamp dimming action – it is more than sufficient for this use-case. The IC has four analog outputs, one for each comparator. The IC is loaded with the desired levels using a three-pin interface consisting of CLK, LOAD and LDAC pins. These are manipulated using software.

dac-circuit2.png

 

Hardware Checks

Run a few checks on the circuit to confirm all is well. For all these tests, do not connect up the board to the RPI.

1. With power off, confirm no short between +24V, +5V and 0V lines with a multimeter

2. Confirm that the +5V connection on the DC connector J1 is connected to the power pins on the three ICs

3. Confirm that the 0V connection on J1 is connected to the 0V pins on the three ICs and to the MOSFET source pins

4. Now power up, and confirm with a multimeter that the regulator delivers 5V, and confirm that the regulator is not hot - it should be between cold and about body temperature if all is working well

5. If you did not do it earlier, confirm with headphones and a 100nF capacitor in series that you can hear a tone as described earlier. Once this is confirmed, snip or desolder the C4 capacitor.

6. Place a 10k resistor between the DATA pin of the DAC and 0V (this is easy to do by pushing the resistor into the jumper cable socket that will connect the controller board to the RPI. Place a multimeter across the resistor and confirm that you see 0V. Repeat for the other two signals that will connect the two boards together.

 

Software Installation Details

The steps at this site were used to install node.js, modified slightly:

From the home directory (/home/pi):

mkdir –p development/light
mkdir mytemp
cd mytemp
wget http://nodejs.org/dist/v0.10.21/node-v0.10.21-linux-arm-pi.tar.gz
tar xvzf node-v0.10.21-linux-arm-pi.tar.gz
sudo cp -r node-v0.10.21-linux-arm-pi/* /opt/node
    

The above will result in the node executable being placed at /opt/node/bin being installed.

 

The /etc/profile file needs two lines added before the line that says ‘export PATH’. To do this, type

sudo vi /etc/profile
    

(assuming you know how to use vi; otherwise use an alternate editor). These are the two lines to be added:

NODE_JS_HOME="/opt/node"
PATH="$PATH:$NODE_JS_HOME/bin"
    

Then, reboot the RPI:

sudo reboot
    

 

Once it comes back alive, the next step is to install socket.IO:

cd ~/development/light
npm install socket.io
    

The above command will take about 5 minutes to complete.

 

Now, In the mytemp folder, type the following to install an excellent GPIO library by Gordon (unfortunately I don't know the last name):

cd ~/mytemp
git clone git://git.drogon.net/wiringPi
cd wiringPi
./build
    

The above will download, compile and install the wiringPi library into /usr/local/lib.

 

Place the dac.c file that is attached to this post into the development/light folder (and also the index.js and index.html files while you are at it), and compile it as shown here:

gcc -o dac -lwiringPi dac.c
    

 

The software part is now complete. As a simple test, connect up the controller board to the RPI, plug in the 24V supply (you don’t need to worry about any power-up sequence) and use the command below then confirm with a multimeter that the DAC output pin 12 goes to about 3.7V.

sudo ./dac 0 255
    

The first parameter was the channel number (0-3). If any lights were connected to channel 0, then they would now be lit up (We still need to make the lights, they are described further below).

The lights on channel 0 can be dimmed to any value, such as:

sudo ./dac 0 128
    

To turn the light off:

sudo ./dac 0 0
    

You should see the DAC output on pin 12 vary accordingly as the commands above are entered.

 

Constructing the lights

Depending on your needs you could construct the chains of lamps in different ways. A general topology is shown in the diagram here.

lamps-overview-and-dimensioning.png

The four chains can be bundled together and secured with a small piece of clear heatshrink tube or glue or tape (or twisted together). As expected, the chains are staggered so that light ripple effects run across the bundle. For a thinner bundle although four return wires are shown, they could be reduced to a single wire going to the +24V supply that is common to all four channels.

 

Since this is a custom design you may wish to adjust the lamp spacing for the exact perfect length. There is an excel spreadsheet attached to this post that lets you enter in parameters, and it will calculate the lengths of all the wires (but do add an additional centimetre to the drop length, to allow for wire stripping).

You also need plastic shapes (here are some common translucent colors).

raw-plastic.jpg

The steps to assemble each lamp are described in the sketch here but also in the photographs further below. The clear or colored translucent plastic shapes can be built up to the desired thickness by securing with clear tape along a couple of edges. This means it can be changed the following year if you want a different color scheme.

lamp-assembly-rendering2.png

The lamp assembly is surprisingly fast – just make a couple of holes in the sticky feet (just by hand with a 0.8mm drill bit – no need for a tool), push in the wires, strip the wires about 8mm, twist the lamp onto the wires, optionally solder it, and then attach the sticky feet to the plastic shape with a bit of glue. The wire ends will be kept apart because they automatically fit in between some of the ridges in the plastic shape hole, so no extreme care needs to be taken during assembly (the shaped hole also serves as a lens and to hold the lamp centered).

single-lamp-assembly-steps.jpg

The resistance of each string of lights will be about 23 ohms with the recommended lamps.

This is the final result when lit:

final-lamp-lit.jpg

 

Using the system

Once you have the lights connected up to the board, power it up and go to the development/light folder where the code was placed and enter the following command to start up the program:

node index.js
    

 

Now you can traverse to the web page http://xx.xx.xx.xx:8081/index.html using any web  browser and you should see a lights control panel view like the one shown below. Pressing any button to explore the commands available. There are only two patterns for now but more can be easily added if desired. Pattern speed is adjustable. The status bar will indicate when the RPI has received and processed the commands.

browser-view.png

 

Summary

The lights controller described here allows for 4 channels of dimming and full control from a web browser. Hopefully it can provide further ideas. The software structure based on a Node.js platform can be reused whenever you need to control or monitor hardware remotely via a web browser. The DAC control program, and TI’s 4-channel TLC5620 DAC are ideal for whenever you need a computer-controlled, adjustable voltage for controlling external devices. The MOSFET control described here was fairly simple but is ideal for whenever you want to switch a few hundred milliamps without relays. Portions of the analog circuit were simulated before construction and it is worth getting to know the simulator for trying things out. The actual traces in this post were taken with a Tektronix MSO2024B oscilloscope. The quality of the laser-cut shapes from Problemchild's service was spectacular so I’m looking forward to actually using these lights now. If you are interested in constructing something similar, a parts list is below and the attached zip file contains all the code.

lamps-lit2.jpg

 

Parts List

ID Description Quantity Farnell Part Code

C1 Capacitor 220nF  1 1692301

C2 Capacitor 22uF 50V 1 8766835

C3 Capacitor 10nF 1 1902262

C4, C5, C7, C8 Capacitor 100nF 4 1141777

C6, C9 Capacitor 100nF Axial 2 1902254

IC1 Quad Comparator LM2901N 1 9487697

IC2 Timer NE555P 1 9589899

IC3 TI Quad DAC TLC5620 1 8454493

IC4 Regulator 5V KA78L05AZ 1 1014073

J1 DC Connector 2.1-2.5mm 1 1854512

LMP1-20 Lamp T-1 5V 120mA 20 1139298

Q1-Q4 BS270 N-channel MOSFET 4 1017689

Q5 BC557 NPN BJT 1 9558527

R1 Resistor 2.7k 1 2329509

R2, R4-R7, R15 Resistor 10k 6 9339060

R3 Resistor 1k 1 9339051

R8-R11 Resistor 33k 4 2329515

R12, R13, R16, R17 Resistor 10R 4 9339035

R14 Resistor 3.3k 1 2329522

Misc:

DIL IC socket 8-pin 1 1077344

DIL IC socket 14-pin 2 1077311

Header 40way 2row (cut to 26way) 1 1319210

Proto board (Perfboard) 100mmx160mm 1 1221144

3M ‘Bumpon’ clear feet 12.7mm diax3.5mm 1 2314565

24V 1.25A Power Supply 1 1354829

Terminal block PCB mount 6 way 5.08mm 1 2008008

Wire white 1mm ext. dia. 7 strand 1 1177586

Wire bare 30AWG 1 2290921

Nylon standoff 15mm M3 2 1336157

M3 screw black 6mm 4 1420015

Plastic shapes – order directly by contacting John Alexander

Impact adhesive (UHU or Bostik for example)

Clear tape

 

Files

Zip file here.

Filter Blog

By date: By tag: