The Pixhawk-CHDK trigger will let you use Pixhawk-based drones (like the IRIS+) with a CHDK compatible camera for aerial photography without using a whole mess of duct taped-together UBECs and LED switches and whatnot.
The Pixhawk-CHDK trigger has three input connections in a 0.1" locking header which is compatible with standard servo lead connectors. Power and ground is taken directly from the flight battery (3S or 4S) and the input signal directly from an auxillary output on the Pixhawk. No need for BEC/UBECs or for powering the servo rail on the Pixhawk.
Output to the camera goes directly to the camera's USB port. (Using a locking 2-pin 0.1" header.)
There is also a mini-USB connector for configuring the Pixhawk-CHDK trigger. Configuration is done by connecting the Pixhawk-CHDK trigger to a Mac OS X, Windows or Linux computer and opening a terminal connection (using screen or PuTTY or your terminal application of choice) to the device.
Using a simple command-line interface, a number of intervals (up to 20) can be configured. An interval is simply a definition of an input PWM range and corresponding output pulse length. This will allow the Pixhawk-CHDK to work with all CHDK scripts that use the USB remote control input for control, regardless of how many different commands the script supports.
So if we want the CHDK to receive a 50 ms pulse when the RC signal is between 1800 and 2000 µs, the command would be
Everything is stored in non-volatile RAM (flash) and the interface currently supports the following commands:
help– shows available commands
list– shows all defined ranges
delete– removes a range
add– adds a range
show– shows all or a specific settings parameter
set– modifies a settings parameter
pulse– sends an output pulse of the specified length for testing CHDK scripts
isp– enters ISP mode for flashing new firmware
Everything is open source and open hardware; all schematics, board files and firmware will be made available shortly along with BOM and assembly instructions.
The Pixhawk-CHDK trigger is coming along nicely. The prototype is done and the firmware is almost done.
The firmware is actually very simple. I'm using 32 bit timers for both measuring incoming RC PWM signal for for outputting 5 V pulses of specific lengths and all the USB CDC functionality is copied-and-pasted from a previous project. The most complex part is actually for command-line interface (or "CLI") parser.
To configure the device you plug into your computer using a mini-USB cable and then connect using Telnet, screen or other terminal application.
The command set is pretty simple and supports the following commands:
list -- shows all defined intervals add 1000,1200,85 -- adds a new interval delete 1 -- removes entry 1 change 1=1000,1300,85 -- changes entry 1 pulse 50 -- sends an output pulse of 50 ms show -- shows all settings parameters show <setting> -- shows the value of a single parameter set <settings>=<value> -- changes the specified settings parameter help -- shows available commands ? -- same as "help"
No need to "save" or similar. Everything is stored in EEPROM as soon as it is entered.
The PCB design is also almost done. I just need to check it a couple of times (time well spent, trust me) and verify footprints (likewise time well spent). The size is 5 x 2 cm and even though I probably could squeeze it down some more, I think I'll keep the current size seeing as how I'll be hand-soldering some of the parts and applying solder paste and components all by hand.
Here's a rendering (from the excellent 3D Gerber Viewer from Mayhew Labs:
Here are Eagle schematic and board files as well as BOM for the ROV power board.
I moved all the high voltage/current stuff to a separate PCB and separated the control connections by using optocouplers.
That should help avoiding the electrical noise from the power MOSFETs switching at 20 kHz for the thruster motors.
|1||TE Micro-MaTch 12 pos female||6804978||Or just solder wires directly to the board|
|1||TE Micro-MaTch 12 pos male||6804993|
|1||12 lead ribbon cable||2899852||This is actually 14 leads. Peel off two or use separate wires.|
|6||FOD3180 optocoupler DIP-SMD||6712706|
|7||Screw terminals BLK||4813989|
|7||Screw terminals RED||4813973|
|6||SMD capacitor||100 µF||7472871|
|6||Ceramic bypass cap. 0805||0.1 µF||6480979||Or any other 0.1 µF 0805 ceramic cap.|
For my ROV project, I am considering using a flat acrylic disk instead of a dome for the front "window".
So I needed to calculate if a disk of a certain diameter and thickness would hold up to the pressure exterted at a specific depth.
A couple of hours of Googling led me to these calculations and constants:
The maximum stress a uniformly supported disk is subjected to (of a given material and of a given thickness and radius) is calculated as follows (from here):
|σ =||3(3 + ν)pr²|
|σ||is the maximum stress in Pa|
|ν||is Poisson's ratio for the material (0.37 for acrylic from here)|
|p||is the pressure the disk is subjected to in Pa|
|r||is the disk's radius in meters|
|t||is the thickness in meters|
If the maximum stress exceeds the material's flexural strength, the disk will break.
For acrylic the flexural strength is 100 MPa (from here).
I entered the values for a 6 mm thick 110 mm diameter disk at a pressure equal to 25 meters depth and the result is that the max stress on the disk is 37 MPa. So it will hold.
You can enter your own values in the InstaCalc formula I made here: http://instacalc.com/9335.
For the ROV project I need two UART connections (one for RS485 to the onboard controller and one for receiving input from the VNC2 USB host controller).
And since the LPC1347 only has one UART I needed a soft UART for one of the connections. Fortunately for me, NXP provides an implementation in AN10955. There was only one problem with it: it doesn't work. Or rather, it works for a while and then stops receiving anything (scoping the UART line confirmed that the VNC2 chip continued to send data so the problem had to be in the soft UART code).
Yea, intermittent errors – what's not to like… (Read on for the problem and the solution.)
For the ROV project I need to drive six DC motors (waterproof motors from bilge pumps). They are 12 V DC brushed motors running a 6 amps at full speed and I want to control them using PWM (for variable speed) from an LPC1347 MCU.
A popular way of controlling DC motors is by using an H bridge. However, since I only need to drive the motor in one direction I can use a simpler configuration: a single N-channel MOSFET as a low-side switch.
First I need to find a MOSFET that can handle the 6 amps continously and not get too hot. And since I will switching the MOSFET on and off using PWM at a frequency of 20 kHz I also need to consider switching power loss.
Here are a couple of useful links: choosing a MOSFET, MOSFETs and drivers, MOSFET power dissipation.
Gate current and MOSFET driver
Even though the MOSFET doesn't require a high voltage to fully switch on, the MOSFET gate does have a quite high capacitance (typically, the higher current a MOSFET can handle the higher gate capacitance it has) and in order to switch the MOSFET on and off quickly enough we need a high current (of the order of a few amps).
If the gate current is low it takes longer to switch the MOSFET and the resistance through the MOSFET is much higher when the MOSFET is switching. And higher resistance means higher power loss and higher temperatures.
Since the MCU cannot provide or sink more than 4 mA we'll use a MOSFET gate driver to boost the current from the MCU and to handle the higher sink current.
Flywheel diode and capacitor
I won't go into details since you can read about it in great detail elsewhere (Wikipedia for example) but you do need a diode and a capacitor on the motor circuit. I tried without diode and capacitor with a scope attached. With no flywheel diode there were some really large voltage spikes every time the motor stopped (about 130 V). And without the capacitor (but with diode) there was a nasty "ringing" (starting out a about 20 V) every time the motor stopped.
So the final circuit is:
As kind of a bigger, more long-term project I've been thinking about building a small ROV. This is in no way a novel idea – there are lots and lots og DIY ROV projects out there (Google: build your own ROV). I live by a canal in Copenhagen habour so it would be fun to have a small underwater robot to play with.
There is a lot of hardware going into a ROV project so there's lots of potential for learning new technologies. One of the components is, of course, the control input device. I figured I would forego the usual clunky four-way tact switches and use a decent USB joystick instead – a Saitek Cyborg EVO to be specific. It has pitch, roll, yaw and throttle axes as well as a thumb hat switch and about a million push buttons.
This is a USB joystick and it uses the USB HID protocol. So I need the MCU to work as a USB host. This either involves a big nasty pile of firmware code or a MCU with ROM-based USB host drivers.
My current MCU of choice, the LPC1347, does not have USB host capabilities, but its bigger (but older) brother, the LPC1768 (and other in the LPC17xx series) does have USB host drivers.
However, instead of switching to another MCU I've decided use a dedicated USB host IC. That being the FTDI Vinculum-II. This chip will handle all the USB stuff: enumerating, connecting and so on. And it will be programmed with firmware that simply echoes HID data from the joystick to the MCU using either UART or SPI.
So – off to the store to get myself a development board version of the VNC2 (this one) and we'll see if I can get it working with the joystick…
Success! More or less, anyway.
Using the nxpUSBlib (having made a few modifications – I'll do a post on that soon) I've managed to get USB CDC working and I got the GSM initialization and SMS receiving working.
At the moment, on receiving an SMS, the system will reply to the sender with the current GPS status regardless of the contents of the SMS.
(The GPS has no fix because it is on my workbench with no satellites in view.)
Power supply considerations
But: I need to do some careful design of the power supply. The GSM module is extremely power hungry. Especially when registering on the network or doing any other network related tasks – like sending or receiving SMSes. And the battery I'm currently using can not supply enough power for both the GSM module and (through a linear 3.3 V voltage regulator) the MCU and GPS module.
So I'll have to get a beefier battery (this 2000 mAh one) or this 6000 mAh one) and also add a low ESR capacitor (as recommended in the GSM module datasheet).
And I'll also add P-channel MOSFETs as high-side switches for the GSM and GPS modules in order to be able to switch power on and off to these modules.
At the moment I run the prototype off two separate power supplies: the 3.7 V LiPo battery directly connected to the GSM module and a 9 V battery supplying the MCU and GPS module through a 3.3 V LDO voltage regulator.
I’ve made quite a bit of headway with the firmware for the GPS Tracker project but there are still some problems – mainly with the command parser and the USB CDC interface.
So I decided I needed some way of debugging the firmware. After looking at several options (they have to run on Mac OS X), I decided to get a LPC1347-based LPCXpresso.
The LPCXpresso consists of two parts:
- An LPC MCU with a minimal amount of support components: crystal, capacitors, an LED and a mini-USB socket with the required resistors and PNP transistor.
- The “LPC-Link” which is a programmer and JTAG debugger which connects to the computer by USB. The LPC Link can actually be severed from the MCU part of the board and will then work as a normal JTAG debugger which can be connected to MCUs (LPCXpresso or otherwise) using a 10-pin connector.
The LPCXpresso also comes with a free version of Code Red’s Eclipse-based IDE with built-in/preconfigured support for the GNU tool chain and standard C libraries and debugging views for inspecting memory and peripherals and whatnot.
I prefer the LPCXpresso to the mbed because the MCU board contains no extra components (compared to what I will use on my own boards) and all code is standard C and CMSIS libraries (so no proprietary firmware environment and libraries) – and still I have the ability to debug code and inspect memory at will.
LPC11U24 + LPC1343 –> LPC1347
The LPCXpresso is available with a number of different LPC MCUs. I chose the LPC1347-based one.
Basically, the LPC1347 is a newer version of the LPC1343 and it has the same GPIO structure as the LPC11Uxx devices and the same USB ROM drivers and it now has EEPROM as well. Read this blog entry on microBuilder.eu for a comparison between the LPC1343 and the LPC1347.
I have decided to focus on only one ARM MCU instead of both the LPC11U24 and the LPC1343 – and that will be the LPC1347 (for now at least). Yes, it has a slightly higher power consumption than the LPC11Uxx but on the other hand it is faster and has a Cortex M3 core instead of a Cortex M0 core.
So the plan is:
- Make the necessary changes to compile the current firmware code for an LPC1347 (which shouldn’t be too much of a hassle since peripherals for the LPC11U24 and the LPC1347 are pretty much the same) in the LPCXpresso IDE (removing the current linker script and CMSIS files).
- Rebuild the breadboard prototype using the LPCXpresso.
- Debug, find the problems and fix them…
For the GPS Tracker project I’ve been working on – struggling with, actually – getting all the communications subsystems working. I need to use UART for communication with the GSM module, soft UART (since the LPC11U24 has only one hardware UART port) for the GPS module and USB CDC for command and debugging.
And apart from the occasional programming blunders (like forgetting to increase a pointer when iterating elements in an array) I’ve had lots and lots of weird problems. But I finally got UART and soft UART working together and then I took a really long, hard look at the example USB CDC code I’ve been working with.
And it turned out that I needed to change a couple of things:
- The linker script (which should be for an LPC11U24 device) specified a RAM size of only 4 KB. This has been fixed to specify an SRAM size of 6 KB.
- The USB interface was initialized with a memory buffer at what was, in effect, an arbitrary place in the SRAM memory. The original code used
usb_param.mem_base = 0x10001000and
usb_param.mem_size = 0x1000.
For an LPC11U24, location 0x10001000 is at two thirds up in the SRAM area (which is from 0x1000000 to 0x10001800).
This has now been changed to use
usb_param.mem_base = 0x20004800and
usb_param.mem_size = 0x0800pointing to the top of the USB RAM area with a size of 2 KB (which is the size of the USB RAM).
USB_CDC_send()function calls the
WriteEPdirectly. This has been changed to copy data into a serial fifo buffer and calling
VCOM_bulk_in_hdlr()function when the USB host requests data. And the max packet size is also observed now.
And with these changes in place I was rewarded with the following session on the USB CDC terminal connection:
sys test OK - Response from SYS TEST sys version OK - b155 on 2012-09-02 13:34:17 +0200, git 31db1bb904695fc5347a136dbf2c819520162099 gps status OK - GPS status: 1, sats: 6/12, time: 121246.854, lat: 5538.7522N, lng: 01233.1385E
Next steps are getting the ADC working for monitoring the battery level and implementing the interface for the GSM module.
To continue my GSM-GPS Tracker project, here is an overview of the system and the components it comprises:
The firmware components can be divided into peripheral drivers and core functionality.
The project is hosted on Github and all the driver code along with linker script, startup code, CMSIS files and Makefile has been moved into a Git submodule (the root of all evil, I know, but in this case it actually made sense) so I can reuse that in my other LPC projects. The submodule is also on Github.
- ADC for battery voltage monitoring
- EEPROM for storing/reading settings (already working)
- UART for GSM module communications (already working)
- Soft UART for GPS module comms since the LPC11U24 only has one hardware UART (already working)
- USB CDC for local programming and debugging (already working)
- Command parser for commands received by SMS or USB CDC
- NMEA parser to extract coordinates and timestamps from GPS module output
- SMS receive/reply GSM module interfacing
- Position logging storing current and the X last known positions with timestamps
It’s about time for a new project and I’ve decided to dust off an old project that I never really got started: a GPS tracker with a GSM/GPRS phone module.
Sure, there are plenty of GSM enabled GPS trackers available – both comercially (like this one) and as hobby projects (this one for example) but that doesn't mean that I can’t 1) learn a lot from making one myself, 2) have fun while doing it and 3) make something better than what is out there…
So the initial high-level requirements (aka “what’s it gonna do”) are:
- Get current position from GPS module.
- Accept commands as SMS messages from a GSM module.
- Send position info back as SMS.
- Continuously send position info to a webserver.
And my initial design considerations (aka “keep this in mind when designing the thing”) are:
Everything must be run off a 3.7 V LiPo battery. So think about power consumption and battery capacity.
The LiPo will be charged with a mini-USB cable.
Think about the size and mounting of GPS and GSM modules as well as antennas for GPS/GSM.
We’ll also need access to a USB socket for charging.
Also, the LiPo battery needs to fit in the enclosure.
The components I have in mind for this project right now is:
- MCU: NXP LPC11U24 ARM processor. I’m thinking that is a good project to start switching from AVR to ARM.
- GPS: SUP500F GPS module since that’s what I already have in my parts box. Otherwise I would probably choose a more modern module.
- GSM: Telit GE865 on breakout board – again the reason is mainly that this is what I already have. But it’s still nice.
- LiPo charging IC: The Microchip MCP73831 looks like it fits my purposes perfectly: it is designed to charge one LiPo cell from a USB port and it has bi-directional status output.
- Status LEDs: a couple of 0805 or 1210 SMD LEDs. The exact model is not critical.
- SIM holder: a generic SMD SIM holder. Something like this.
- Battery: 1000 or 2000 mAh 1s LiPo battery. This one for example.
The next step is, of course, cobbling together a prototype. And in order to do that, I will:
- Get the GSM module working: find a suitable SIM, figure out how to send and receive SMS'es and get HTTP GET and PUT working using GPRS.
- Verify that the GPS module works.
- Create block diagrams for hardware and firmaware (i.e. identifying components and dependencies)
It works! Pretty darn well in fact!
Although I did have a couple of minor problems when I had assembled the board.
First, I could not connect to the BLE112 module with the CC Debugger in order to load firmware onto the Bluetooth module. Not so good... I spent quite some time tracing the connections of the programming header and the BLE112 module and comparing with the prototype but everything seemed to match so I feared I had a malfunctioning BLE112 module. Which would bad since those are by far the most expensive part and not easy to unsolder – in fact, it would probably require ordering more parts and building a completely new board. However – a bit more connection tracing, this time at the pins of the 2.54 to 1.27 mm adapter board attached to the CC Debugger, revealed that there was a faulty ground connection. It looks like it's the pin on the programming header itself that has a poor connection. Fortunately I can fix this by making a temporary green-wire fix (by temporary I mean hand-held) while programming the module. Whew!
Then came the next problem. I had actually discovered this when I was assembling the board: I had forgotten the 4k7 Ω pull-up resistors for the I2C interface of the EEPROM! Doh! And it turned out that the ATmega couldn't communicate with the EEPROM. This was easily fixed, however, by simply activating the ATmega's pull-ups for PC4 and PC5.
With the problems fixed, everything worked like a charm. With all IR LEDs in place the range is excellent (tough I have yet to see if I can control the neighbors' TV sets :). And it looks just awesome in its laser-cut acrylic case with countersunk screws and threaded insets (so no screw heads or nuts protrude from the case).
There is still a bit of iOS app programming remaining, like converting the app to a universal app so it'll run on iPad as well as iPhone.
Enjoy the pictures – click for full-size version:
While the PCB is getting made, I've done some work on the enclosure.
It is being made from five layers of 5 mm transparent acrylic from Ponoko.The layers are held together by M3 countersunk machine screws. While the front and middle layers have 3 mm holes for the screws, the rearmost layer has 4 mm holes for fixing the screws by using threaded insets. The rearmost layer also has three holes for mounting the PCB. The PCB will also be mounted with M3 screws into threaded instets and lifted a bit off the back using nylon spacers (which I need since there are a couple of through-hole parts).
The opening in the bottom of the middle layers are for the DC power plug.
(Click for large versions.)
And here's a short animation – click to play video:
I've done some more work on the app. It is now possible to configure the user interface by way of an XML file. At the moment modifying the XML file requires building the app again but this will be changed so the XML file can be downloaded and uploaded from within iTunes.
The XML file specifies a number of "pages" (in the screenshots I have two pages: "TV" and "Channels"). The user swipes sideways to navigate between the pages.
Each page has a layout that specifies how large the buttons are and where they are positioned. Right now the app only supports "medium buttons" (3 x 4 buttons) and "large buttons" (3 x 3 buttons) but more will be added.
Each button position on a page can be left empty or hold a button. A button is configured with an ID (the command ID used – thus the same command can be sent from more than one button), a color (which sets the button's background image), a text and a mode. Mode is either "normal" (command is sent on touch up), "touchdown" (command is sent on touch down) or "repeat" (command is continously being sent as long as the button is pressed).
View a sample configuration file here.
Screenshots – click to see full screenshot:
The PCB for the BLE multi-remote is done and it looks like everything fits. Except for the 10 µF capacitor (left side, middle) where I've used a C instead of B sized footprint. This is why you should always print out a 1-to-1 sized version of the PCB and place the actual components on it (never mind the values, of course, as long as the correct packages are used):
Oh, and if you can't find the TSOP34838 IR receiver anywhere then that's because I forgot to include it in the schematic and board… I just realized that. Doh!
Anyway, it's been added where C7 (bottom-middle) is now and C7 has been moved a bit to the left and up and rotated 90°.
I've run into a few problems with the AVR firmware. (The GitHub repository for which is located here.) Recording of IR signals works fine and the values I record correspond nicely to the theoretical reality ("theoretical reality"?). If you can't remember the protocols and timings, you can find a great explanation of the various protocols here.
But – when I send the signals they are too long (as recorded by my oscilloscope connected to the output pin of the MCU which controls the IR LEDs).
My first approach was:
_delay_us( high_duration );
_delay_us( low_duration );
First I tried simply subtracting a "trim" value from each recorded duration. Which almost worked. But the necessary trim value became so high that, for short durations, the total delay became less than zero microseconds (which, of course, was interpreted as a really high number instead). And even if I clamped the delay values so they couldn't be less than zero, the pulses were still too long.
So instead I now use the 16 bit TIMER1 (TIMER0 is used to generate the 38 kHz output to modulate the IR signal). I configure the timer for CTC mode with the same duration as when sampling IR signals. When learning signals I increase a counter (16 bit resolution) to record the pulse as a number of "sample intervals".
Now when sending, I simply use the raw recorded counter value and decrease a counter on every compare match of the timer. When reaching zero, I toggle the IR signal and reset the counter to the next value in the recorded sequence. When I reach a counter value of zero I stop the timer and the signal is complete.
And a whole 'nother thing is that I've been running the MCU on 3.3 V at 16 MHz. Which according to the datasheet (section 28.3 Speed Grades) is out of spec. Sure, it may well run fine but in this case where timing is crucial I had better throttle it down to 12 MHz which is inside the Safe Operating Area.
And lo and behold – everything works!
The first revision of the PCB layout for the multi-remote project is done. Mind you, I always go through a couple of revisions before getting it manufactured (because I always mess something up in the first few attempts).
I've made a couple of upgrades to the iPhone app: it now has four command buttons as well as "Toggle debug window", "Record IR" and "Scan for devices" buttons. The command buttons and the Record button are only enabled when a device is connected. And the Scan button is only visible (replaces the Record button) when no device is connecte
The app now starts searching automatically when becoming active. If it discovers the last device it was connected to, it connects immediately. Otherwise, it shows a list of devices and lets the user pick a device to connect to. Only devices that advertise the correct service UUID are listed.
The UI also got a little upgrade – it's still just a prototype, mind you...
Also, I've added a MOSFET (IRL1404 – for the PCB version I'll use a IRLML2502) to drive the IR LED with more power. Before, the LED was just driven directly from a MCU pin (which, as everyone knows, is bad form). Now, the MCU pin is connected to the gate of the MOSFET (logic-level) which turns on the LED and current limiting resistor for 100 mA in a common-source configuration.
As expected, the range improved tremendously. And I'm still only using one wide-angle LED.
I have gotten a prototype assembled and working. So far, I've got the following working:
- Connect and disconnect to devices advertising a specific service UUID
- Automatically connect if a known device UUID is found
- Read RESPONSE attribute (although it is not used for anything at the moment)
- Receive notifications when the RESPONSE attribute is updated
- Send commands by updating the COMMAND attribute
- Send commands to the MCU over serial USART when the COMMAND attribute is updated. (Only the command type is sent now – the sequence ID is not yet included.)
- Commands are also sent to the MCU when a client device connects or disconnects (which is ignored at the moment).
- Record an IR signal and store it in the EEPROM.
- Playback the IR signal stored in EEPROM (or a hardcoded test sequence).
- Write the stored IR signal to serial for debugging.
- Respond to commands received on the serial line and trigger recording, playback or one of the debugging commands.
And it works! I can switch my television on and off from my iPhone :)
Next step is to use both high-intensity and wide-angle IR LEDS and to drive them at much higher power (right now the one wide-angle LED is being driven directly by the MCU – which you should never do).
Here is a picture of the prototype in all its glory:
And here is another picture with the individual parts labelled:
Here's some notes on how to store IR codes for the IR controller project:
If I were using pre-programmed codes in a few known formats (like RC-5 or NEC1) I could store the commands using just the two or three bytes that actually make up the sequence. For example, a NEC sequence consists of one address byte and one command byte (although it is sent as a lead-in followed by four bytes).
But mostly I will need to record IR signals and store those. The proper way of doing it would probably be to parse the recorded signal, identify the protocol and store the required few bytes. But that sounds like way too much work. So instead I'll just be storing the time intervals for on-off pairs. I would like to use one byte for each time code and if I use 100 µs resolution I will get from 0.1 ms to 25.5 ms in .1 ms intervals. I think that might be good enough – but time will tell :)
Firstly, an ATmega328P has only 1 KB of EEPROM storage. And most likely, that will not be enough. So I'll be using an external EEPROM chip. The "24C" series seems to be very widely used and uses a simple I2C protocol. So something like Microchip's 25LC512 seems suitable (512 Kbits, 3.3 V and is available in both DIP and SOIC packages) and will give me an extra 64 KB of non-volatile memory. I'm thinking that will be enough.
The IR codes will have differing lengths. And the correct way of storing those in the EEPROM would involve some kind of allocation table and stuff in order not to waste memory space. But instead of messing around with all that I've decided to go for a super-simple solution there every IR code uses a fixed size (like 128 bytes – something that is a whole multiple of the EEPROM chip's page size). That way I can easily access the code for a specific index.
The data will be in raw time-on, time-off format and terminated by a 0 value (since a 0 ms pulse will never occur).
Thus, for my LG television which uses the NEC1 protocol, an "off" command (address 0x04, command 0xC5) can be stored like this:
06, 06, 06, 06, 06, 17, 06, 06, 06, 06, 06, 06, 06, 06, 06, 06,
06, 17, 06, 17, 06, 06, 06, 17, 06, 17, 06, 17, 06, 17, 06, 17,
06, 17, 06, 06, 06, 17, 06, 06, 06, 06, 06, 06, 06, 17, 06, 17,
06, 06, 06, 17, 06, 06, 06, 17, 06, 17, 06, 17, 06, 06, 06, 06, 00
For a total of 67 bytes for a code that basically consists of two bytes! Way inefficient, I know, but it's easy to use.
Using a size of 128 bytes for one IR code will accomodate codes of up to 64 IR pulses and I will be able to fit 512 codes into the EEPROM – and that should be more buttons that I'll ever need. (Maybe I will need to up the size to 256 bytes – we'll see.)
I've made some progress on the BLE112 module. So far, I have:
- Got it wired up in the most basic configurations (VDD, GND, debugging and RESET and TX/RX for UART1, alternative 1 and UART0, alternative 2).
- Got the CC Debugger working.
- Created a project consisting of a hardware setup specification, a simple GATT specification and a BGScript.
- Created an iPhone app that scans for Bluetooth LE devices with the required service UUID, connects to a peripheral and finds the two required attributes (one for sending commands to the BLE112 and one for reading responses).
So far, so good. But I've run into a small problem: I can send serial data from the BLE112 (in response to a startup event or when an attribute changes its value – like when the iOS app writes a value to the command attribute) but I can't seem to receive serial data on the BLE112. Everything should be configured correctly (I think) but the event handler simply doesn't get called in the BGScript.
Maybe the port needs to configured differently. Or maybe I will give up and try using SPI instead and see if that helps.
However, since the BLE112 is used only to receive commands from the iPhone and pass them on to the MCU (like "send IR code such-and-such"), I may not even need to send data from the MCU to the BLE112...
I'll do some more troubleshooting and see if I find a solution.
(It seems I'm not the only one with this problem.)
For my day job, I develop iPhone apps. Fairly often people are interested in developing an app that interacts with some sort of hardware device. Usually the setup they envision is not feasible, sometimes it's nowhere near possible. But I digress...
To demonstrate one possible iOS-to-hardware setup, I made a small prototype consisting of a GainSpan GS1011MIE Wi-Fi module, an ATmega328 and a LED (if you understand Danish or know how to use Google Translate, you can read about it here.)
Wanting to build something slightly more useful than remote controlled LED, I came up with the idea of a remote controlled IR remote control (yeah I know, "remote controlled remote control"). Specifically, a remote control that can control everything from TV, DVD, Apple TV and set-top box which is controlled from an iOS app.
Initial ideas in no particular order include:
- Powered by external 12 V (or 9 or 5 V) adapter
- Use both wide and narrow angle, high intensity IR LEDs (just like the TV-B-Gone) so exact placement is not terribly important
- RTC so it can be programmed to perform actions (macros) at specific times
- Use an IR receiver to learn remote codes
- GS1011M Wi-Fi module (which will also allow the device to be controlled from a browser or whatever) or
- BLE112 Bluetooth LE module (in which case the device will not be connected to the Internet but it will allow much smoother integration to the iPhone app)
- Enclosure: either 3D printed (Shapeways) or layered laser-cut acryllic (Ponoko)
Further bulletins as events warrant…
As mentioned in my previous post, noise from the ADXL335 accelerometer readings result in flickering light. And I don't want that.
(Read the entire post to see chart comparisons of the two filtering methods.)
I got the PCBs yesterday and promptly set about assembling one. The really interesting part of that, of course, was whether it was possible to hand-solder the LFCSP ADXL335 accelerometer ("lead frame chip scale package" – who comes up with these names?).
It turned out it was, in fact, possible. The bottom pad is not soldered, of course, and even though I had made the pads longer to be able to reach them with the soldering iron it was still kinda tricky. But it worked. In first attempt, even.
And the little tumbler thingie works perfectly! (I'll post a video.)
But I need to tweak the firmware a bit. The sensor data from the accelerometer has quite a bit of noise and this results in too flickering light. So I will need to implement a filter of some sort. Either a moving-average filter or a simple low-pass filter. And maybe also some way of "snapping" to 0, 0.5 and 1 values in order to get more "clean" colors. Stay tuned…
"Information wants to be free," as we said back in the day when I was young and naïve
and needed the money and a wannabe-hacker... Now, of course, we say, "open-source everything".
So here they are:
Eagle schematic and board files for the RGB Tumbler
Firmware source code
The PBCs have only undergone minor revisions and Gerber files have now been sent off to ITead Studio for fabrication.
Here's a 3D rendering of both sides of the PCB (yes, several of the components were unknown to Eagle3D and I didn't bother creating custom parts). Also, the largs pads for the RGB LED are actually mostly covered by soldermask:
First version of the PCB for the RGB Tumbler is ready. Although usually I do through a couple of revisions before I send it off and get it made.
The PCB ended up somewhat larger that I had originally planned. It is currently 3.6 x 3.6 mm.
Here are pictures of the PCB printed in 1:1 scale and populated with components to verify that everything fits (click for larger images):
I need to move the slide switch a bit up to make room for the 10 µF capacitor. And I will also move the battery holder up a little bit. The NCP1402 voltage booster almost touches it. Apart from that, everything looks pretty good.
Another problem is that I ended up placing several vias directly under thethe battery. This may not be the best thing. Especially since the vias on ITead's PCBs (ITead Studio is where I get my PCBs made) are not always completely covered (even though the Gerber files say they should be covered). I guess I'll just have to cover the vias myself with some tape or something).
Here's the prototype of the RGB Tumbler in all its glory – click to see hi-res image:
The prototype has been assembled and the first version of the firmware (including the no-button, Gauss-Newton calibration) is done. The calibration routine has been converted from Rolfe Schmidt's Arduino sketch to raw AVR Libc.
Here's a video of the prototype being put into calibration mode, calibrated and then turned on in normal mode.
The camera doesn't do the RGB LED credit and the colors aren't reproduced very well – probably because of the high intensity of the LED.
And I have changed the colors a bit since the last few posts. So now a white light on power-on means "if you switch off now the device will go into calibration mode on next power-up". And the blue flashing LED means "switch to next orientation and hold the sensor still". After a reading it will flash twice either green (meaning "reading ok") or red (meaning "bad reading – hold it still, man") and lastly it will keep flashing green meaning "calibration done – cycle power".
When in normal mode, the G readings on each axis are clamped to 0-1 (I'm using the absolute value, so -1 G is the same as +1 G). This is then converted to a PWM duty cycle between 0% and 100%.
Red is the X-axis, green is Y and blue is Z. That's why it lights a solid blue when lying flat on the table: the only acceleration is 1 G on the Z-axis.