When I was first starting out, I worked with a senior engineer who had a poster in his office that said “It’s hard to remember that the objective was to drain the swamp .. when you’re up to your @** in alligators”. I bring this up because this part of my investigation of the Embedded Pi reminded me of that poster ..
I initially started to check out the “ST-Adapter mode” of the ePi. CooCox’ web site had a couple of projects along this line, so I started with this one: Getting Started with the Embedded Pi and Raspbian. This is a simple project to blink the ePi user LED from the RPi; foolproof, right?
Not so fast .. I followed the instructions and created and compiled the files, then attempted to download them to the the ePi. Once I had solved the mystery of the stm32loader.py program (start the program, wait until it says "None" then reset the ePi with the BOOT0 switch held down), I downloaded the led.bin to the ePi .. and nothing.
So, I fired up the debugger, cloned the C sources to my Windows box, compiled the demo, brought up the debugger .. and nothing amiss at all. Ok, now to the schematics... Turns out that sD13 (the user LED) on the ePi is GPIO17 on the RPi, and the GPIO drivers on the RPi holt that pin low (ie, logic ‘0’).
I fixed this problem the hard way, by blacklisting the gpio drivers in the file /etc/modprobe.d/raspi-blacklist.conf and rebooting. In hindsight, I could have just as easily disconnected the ribbon cable from the Pi and the demo would have worked fine.
For anyone interested, here’s what needs to be done to blacklist the RPi GPIO drivers:
Edit the file /etc/modprobe.d/raspi-blacklist.conf
#uncomment these two lines
blacklist spi-bcm2708
blacklist i2c-bcm2708
#add these two lines
blacklist leds_gpio
blacklist led_class
Then reboot the Pi.
However, this example didn’t really show the “STM Adapter Mode” as the Pi wasn’t really controlling anything -- so I went on to another example.
The next project was Raspberry Pi + GUI to Control RGB-LED. The objective of this example is to use the Pi control an RGB LED attached to the Embedded Pi. Simple example, right? Well, as it turned out, there is quite a bit to this example that is not obvious.
The first obstacle was that the hardware setup. CooCox provides a list of hardware requirements but the instructions fail to mention that the LED will require RESISTORS, to keep from letting the “magic smoke” out. No big deal, grab the datasheet and calculate the required resistor values. (In case anyone doesn’t want to figure it out, I used an 150-ohm resistor on the red lead and 100-ohm on the green and blue leads .. check the data sheet for your LED; YMMV). Also, it wasn’t clear from the picture exactly what pins were being used, so check the source: Red = sD3, Green = sD9, Blue = PB9 , (labeled “31” on the ePi).
OK, hardware, check. Now for the software.
The git clone command in the article didn’t work, but a little research turned up the following:
git clone http://github.com/coocox/embeddedpi.git
git clone https://github.com/machunyu/embeddedpi.git
The sources are the same, AFAIK.
So I fetched the source onto the RPi, then download the included binary to the ePi, run the python script and things should be peachy, right? Well, maybe not. Before the python script would run I had to install the python Qt4 bindings, as this step wasn’t shown in the instructions. Here's the command:
sudo apt-get install python-qt4
Once that was done, I was able to execute the demonstration program (see screenshot):
So moving the slider to the right should result in the color shown in the window, right? Well, the result of this were nothing like I expected. Rather than getting various combinations of colors, I seemed to get one color or another -- whichever color that I had last changed was the only color seen. Also, the LED’s became DIMMER as I increased the position of the sliders. Hmm … interesting.
RGB LED 101:
There are two types of RGB LED’s, common cathode and common anode. The difference is in how the diodes are connected internally, thus how they are driven:
To turn on the common cathode type, voltage is applied to the desired anode. To turn on the common anode type, the desired cathode is connected to ground. As you can see, then the common-anode type of LED will be active-low and the common-cathode type will be active-high.
Based on the operation of the sliders, I guessed that the author of the demonstration had used a common-anode LED, while I was using a common-cathode LED. No problem, part of the magic of embedded systems is that I can fix problems in firmware rather than having to redo the hardware. (None of us would ever fix broken hardware with firmware .. right?)
After a few hours with an o-scope, the program and library source, and the CoIDE debugger I had made several interesting discoveries:
1) The CooCox library configures the STM32 PWM in “Mode 2”. Mode 2 holds the PWM output inactive until the count reaches exceeds the programmed threshold, specifically until (TMR1_CNT > TMR1_CCR1). This effectively inverts the PWM waveform. The demo firmware sets the duty cycle to (255 - val) * 100 / 255, which inverts the waveform again.
2) The demo firmware re-initialized the PWM timers each time that it was called (every time that the color value was changed), resulting in all three channels being set inactive.
3) The STM32 timers are sophisticated and feature-rich, but the documentation is not easy to understand.
4) In the CoIDE debugger has a very cool feature: in the “peripherals” window, clicking on a register will bring up a window with the bitfields decoded. This has the potential to save hours of looking up registers in the datasheet; Unfortunately, the debugger didn’t always read the peripheral registers and I never could figure out how to make it do so (see screenshot).
5) Accidentally resetting the RPi almost invariably corrupts the SD card.
In order to get the example to work as expected, I modified the demo firmware to initialize the PWM only on command and changed the code setting the duty cycle to remove the inversion. My changes can be retrieved from https://github.com/bprewit/embeddedpiif anyone is interested.
I was impressed with the framework used in the demo programs; it looks like it could be an excellent starting point for an application. The program accepts commands from the RasPi over the serial port, formatted as follows (from color.py):
self.uart.write(0xa5) # command start
self.uart.write(0x40) # command byte
self.uart.write(0x05) # command number
self.uart.write(0x01) # function number (1 = set red value)
self.uart.write(0x01) # parameter length
self.uart.write(value) # parameter
self.uart.write(0x5a) # command end
The command numbers correspond to a command table in the firmware, which is set up as follows (from demo/02.RGB_LED/Framework/Frame.c):
CmdRegister(0x00, 0x00, SystemCtl);
CmdRegister(0x40, 0x00, MotorShieldOperation);
CmdRegister(0x40, 0x01, TinkerKitOperation);
CmdRegister(0x40, 0x02, UltrasonicSensorOperation);
CmdRegister(0x40, 0x04, DigitalCompass);
CmdRegister(0x40, 0x05, RGBBlinky);
Sending command #5 calls the function “RGBBlinky”, which then is free to interpret the function number and parameter however is required (from demo/02.RGB_LED/Apps/Interface.c):
switch(pCmdStruct->cmd_3)
{
case 0x01: // R
RGBColorSet(R_PWM, (pCmdStruct->rx_buf[0] * 100) / 255);
pCmdStruct->ret = TRUE;
pCmdStruct->tx_len = 0;
break;
case 0x02: // G
RGBColorSet(G_PWM, (pCmdStruct->rx_buf[0] * 100) / 255);
pCmdStruct->ret = TRUE;
pCmdStruct->tx_len = 0;
break;
case 0x03: // B
RGBColorSet(B_PWM, (pCmdStruct->rx_buf[0] * 100) / 255);
pCmdStruct->ret = TRUE;
pCmdStruct->tx_len = 0;
break;
case 0x04:
RGB_Init();
pCmdStruct->ret = TRUE;
pCmdStruct->tx_len = 0;
break;
default:
pCmdStruct->ret = FALSE;
pCmdStruct->tx_len = 0;
break;
}
I added command #4 so that the PWM would be initialized only once, then added the code to execute this routine to the python script.
The CooCox CoIDE is usable; I’ll skip my usual comments about windows-only development tool (especially as the IDE appears to be Eclipse-based). At some point I'd really like to set up the tools on my Linux system, but for the time being I'm stuck with Windows. I didn’t find any glaring deficiencies, other than the peripheral window mentioned above. I had no major complaints.
All in all, what started as a simple task (running a demo program) quickly became much more involved than I had expected. I would have expected CooCox to have provided clearer instructions for the demonstration and I can certainly see an inexperienced person completely giving up in frustration very shortly. However, at the end of the day I had a good idea of how to implement the ST-Adapter mode of the Embedded Pi.
In Part III I’ll cover the RasPi mode, controlling the Embedded Pi I/O directly from the RPi.