Thanks for the feedback and the kickstarter link. That was an interesting project. I have seen a number of Arduino-clones with varying functions on kickstarter. Would be nice to see a project or two with software as the main focus instead of just hardware. Will soon need to produce a board and/or shields to fund further development of Cosa
A note to the BMP085 driver: you may add the barometric pressure reading, as the pressure you measure now is the "absolute pressure". Thus, if you want to see the barometric pressure your local weather station reports (ie. a local airport) you have to calculate "Barometric pressure adjusted to Sea Level" (as this is how they report it).
You have to provide your Altitude (in meters over the sea level) as well.
For example:
/**
* Return latest calculated Absolute pressure from temperature and pressure
* raw sensor data.
* @return calculated pressure in steps of 1 Pa (0,01 hPa).
*/
int32_t get_ABS_pressure()
{
return (m_pressure);
}
/**
* Return latest calculated Barometric pressure from Absolute pressure
* and your altitude over Sea Level.
* You have to provide your Altitude [meters] over the sea level.
* @return calculated pressure in steps of 1 Pa (0,01 hPa).
*/
int32_t get_BSL_pressure(int32_t myAltitude, int32_t ABSpressure) {
float p;
p = ABSpressure / pow((1.0 - ( myAltitude / 44330.0 )), 5.255);
return (int32_t) p;
}
PS: to avoid a "chicken-egg" situation, you may get your Altitude by changing the altitude in above function until the BSL reading is equal to the number your local weather station reports (most current report, as the pressure changes with time and location).
Thanks for your suggestions. I guess this formular could also be transformed and used to calculate for instance height using relative change in pressure. From a design perspective I want to isolate these types of calculation from the sensor drivers and provide them in a separate class/library.
This week the focus has been on improving the support for low-power mode and pushing the default idle mode as low as possible. I have added a number of example sketches to show how to go towards ultra low power (1-10 uA range) in power-down.
Below is a link to one of the sketches. It is a basic wireless temperature sensor using DS18B20s and Cosa Wireless interface and drivers (NRF24L01P, CC1101 or RF 433). The sketch will power up and issue a conversion request to two DS18B20 sensors. Sleep until the conversion to complete (750 ms). After that the temperature samples are read and sent in a message together with a sequence number and the power supply status (i.e. battery voltage). The results for an Arduino Mini Pro 16 Mhz with Power LED removed with the VWI driver and a RF 433 module are;
Power Idle Sampling Transmitting
LiPo 3.9 V 40 uA 1.3 mA 6 mA
FTDI 5,1 V 190 uA 1.5 mA 10 mA
Further reduction is possible by removing the regulator from the Arduino Mini Pro and running on the internal 8 MHz clock. On an Arduino LilyPad the power down mode is less than 1 uA.
I did happen to notice one discrepancy between the NRF24 and CC1101 code in that the NRF24 uses EXT4 on the Mega while CC1101 uses EXT0.
The programs upload and start fine, I just don't see any "traffic".
I'm using the transceivers right out of the box, assuming that the Cosa driver applies necessary any configuration parameters, correct? Can you offer any advice on debugging this issue?
Actually your setup looks fine. The default settings for NRF and CC use IRQ from D2 which is EXT0 for Uno and EXT4 for Mega. I use a Nano IO Shield and a Mega Prototype Shield. Both with NRF 2X5 connector to SPI, etc.
I rigged up a Mega running CosaWirelessSender and a Nano running CosaWirelessReceiver to verify. There are a fair amount of configuration ;-). Anyway it works as it should; both ways.
After the latest improvements for low power mode I needed to adjust CC1101::await() to get the correct wait behaviour between transmitted messages. The broadcast message in CosaWirelessSender could go missing.
Before adding this line (563) to CC1101.hh:
Board::ExternalInterruptPin irq = Board::EXT4)
would it have fallen through and used EXT0?
For some reason, I originally used the documentation in NRF24L01P.hh since I knew the two chips were supposed pinout-compatable, so I had the IRQ connected to pin D2 at first. After not seeing any traffic, I perused CC1101.hh and thought that the logic alleged that EXT0 was going to be used for the Mega. Still nothing.
After seeing your response, I switched the pin back to D2 and still wasn't having any luck. The two transceivers were sitting within a few inches of each other, but I didn't have antennas plugged into the sma connectors. Apparently these boards/chips have zero range without antennas, as I finally saw some messages to appear on the CosaWirelessReceiver board after putting the two sma connectors right against each other. After attaching some antennas, things started working consistently. So that was likely my problem from the start. Doh! I thought they should be able to reach a couple feet without antennas though... oh well.
After getting this to work fairly reliably, I have run into a situation where the CosaWirelessReceiver appears to stop receiving data after going out of range and then coming back. Simply pushing the reset button on the CosaWirelessReceiver board causes data to start flowing again. Have you run into this?
Thanks for verifying my configuration and taking the time to setup your own test -- I greatly appreciate it!
sirhax:
Before adding this line (563) to CC1101.hh:
Board::ExternalInterruptPin irq = Board::EXT4)
would it have fallen through and used EXT0?
For some reason, I originally used the documentation in NRF24L01P.hh since I knew the two chips were supposed pinout-compatable, so I had the IRQ connected to pin D2 at first.
@sirhax
Thanks for the feedback. Yes, the update was to avoid this problem and make the pin-out symmetrical for these types of CC1101 and NRF24L01P modules. You were on the right track. I ran into the same problem with the antenna when first testing the CC1101 modules ;-/
sirhax:
After getting this to work fairly reliably, I have run into a situation where the CosaWirelessReceiver appears to stop receiving data after going out of range and then coming back. Simply pushing the reset button on the CosaWirelessReceiver board causes data to start flowing again. Have you run into this?
No, havn't seen that. Need to rig up the test boards again and see if I can force that to happen. There is basically only one wait loop in CC1101::recv() that could cause this and it waits for either a receive interrupt or a timeout. See if I get some time later this week. Off to Stockholm for a few days.
Previously I have presented some of the details on the object-oriented nature of Cosa and how this helps achieve higher performance (X2-X10 compared to Arduino/Wiring). There are actually more important differences regarding the software architecture and development principles.
One big difference between Cosa and other Arduino cores is that Cosa is a single source code baseline for a large set of boards, processors (e.g. Uno, Mini Pro, Nano, LilyPad, Might, Mega, Tiny), modules and hardware devices. Over 25 different hardware module/devices are supported, not counting different adapters. Variant handling is built-in and may be extended without duplicating or forking the baseline. This allows you to retarget your sketches and move seamlessly between the supported targets. The main difference and restrictions are the available hardware resources (memory, hardware modules, etc) and performance (clock frequency, instruction set, etc). http://dl.dropboxusercontent.com/u/993383/Cosa/doc/html/d5/d1f/classTWI_1_1Driver__inherit__graph.png
The Cosa support classes for SPI and TWI have the same interface for all targets. On ATtiny they are implemented with the USI hardware support. The same interface allows all the SPI and TWI device drivers to be reused on all targets without changing a single line of code. Both SPI and TWI classes implement a higher level of support for protocols and make device driver implementation easier (see iovec_t). The SPI interface also handles multiple SPI devices correctly even if the devices use the bus in different modes and/or speed. The ATtiny USI SPI implementation supports all modes; clock polarity and phase. http://dl.dropboxusercontent.com/u/993383/Cosa/doc/html/df/dea/classIOStream_1_1Device__inherit__graph.png
This style of handling variability is also used for some of the abstract device classes such as IOStream, LCD and Wireless. Implementations of these are also interchangeable. For some of the implementations there is yet another layer of adaptation to reduce the source code baseline and make it easy to move between different wiring/connections. The LCD driver implementation for HD77480 contains its own adapter abstraction seven different methods of connecting to the LCD device. The same LCD interface is also implemented for PCD8544 and ST7565. http://dl.dropboxusercontent.com/u/993383/Cosa/doc/html/d0/d5f/classHD44780_1_1IO__inherit__graph.png
Another big difference is that Cosa has low power support built-in. Cosa uses an event-driven implementation strategy to avoid busy-waiting. This reduces power consumption dramatically (from 10-50 mA range down to 1-10 uA range and below).
that Cosa is a single source code baseline for a large set of boards, processors (e.g. Uno, Mini Pro, Nano, LilyPad, Might, Mega, Tiny), modules and hardware devices
Any port to M0+, M3, M4 or something like that in planning?
pito:
Any port to M0+, M3, M4 or something like that in planning?
Got my hands on a few TI MSP430 LaunchPads but I can't say when I would have time for that. I still have to figure out the tool-chain and the hardware details before porting. There is an Arduino port so some of the work is already done.
For ARM (e.g. Arduino Due) I would like to reduce the amount of tuning for AVR 8-bit (int8_t/uint8_t) and go for more generic and portable (int/unsigned int). Also I would like the toolchain to become more stable.
Still the amount of work is fairly large so I need to dig into the details before doing a plan (to answer your question in classical Dilbert style ;)). Anyway this will not be happening this year as the focus right now is wireless networking protocols including a version of Google Protocol Buffer for data encoding/decoding .
Any port to M0+, M3, M4 or something like that in planning?
I've done quite a lot of work porting the Arduino core stuff to an M0 (LPC1227), I probably won't continue with it partly because other projects like Cosa seem to be 1000% better
I have half a mind to port Cosa to LPCs but don't really have the time at present.
I guess the actual chip is more important than the ARM core though given that (I would assume) once you get the sysTick worked out almost all the code deals with peripherals.
I think I need to add a line or two regarding porting to other processors.
Cosa is right now very much adapted/optimized for 8/16-bit MPUs with very limited memory (SRAM). Moving to something with 8 Kbyte SRAM or larger I would redesign the core towards a true micro RTOS with threads, semphore, message queues, the works :). There is no way to scale upwards without that. The device driver layer would be rewritten. And the programming model moved towards active objects (actors).
I would redesign the core towards a true micro RTOS with threads, semphore, message queues, the works
That would be a lot of fun to do but is all that necessary, could turn into bloatware.
I admit that some simple scheduling would be nice, and once you do that semaphores etc tend to follow. And event queues would be nice especially if usable with an FSM....
I think by using ChibiOS / NilRTOS (use same HAL as of v3) as the RTOS, adapting COSA is not to much work.
I already can use parts of COSA using ChibiOS without any problems (for instance the whole digital/analogue pin OO implementation) and it does make my software a lot easier to read and maintain.
In some parts (for instance SPI / TWI stuff), I have to add locks (semaphores) to make sure things won't lock up or crash. Furthermore I don't use the events, as this does not play nice with ChibiOS, but that's about it...
If that synchronization functionality is implemented in COSA by a sync object that either does nothing (default COSA) or calls the underlying RTOS, the user of the COSA objects won't even notice the RTOS.
The only problem I see is that COSA disables interrupts on a lot of places...
sirhax:
After getting this to work fairly reliably, I have run into a situation where the CosaWirelessReceiver appears to stop receiving data after going out of range and then coming back. Simply pushing the reset button on the CosaWirelessReceiver board causes data to start flowing again. Have you run into this?
@sirhax
I have been able to force this behaviour and found what I think was the problem. Pushed a fix for this. See Improving CC1101 device driver robustness; flush receive fifo. · mikaelpatel/Cosa@19b2f9e · GitHub. Basically the receive fifo could contain incomplete messages as the interrupt is only generate for complete messages (correct address, length, crc). I had assumed that this was done automatically and illegal frames discharged.
Need to check if the NRF24L01P also has this behaviour.
The Cosa synchronized blocks are used to achieve consistent updates and are very short (in the range of 10-50 us). Long interrupt disabled blocks are avoided as Cosa is interrupt and event driven. Very few of these block would or should be replaced by semaphores (or rw_locks). It is consistency on another level of abstraction.
Anyway this is an important issue how to use a RTOS and write code that is still bare-metal and uses very little resources (SRAM). Would like to know more about your experience with this. Great job!
sirhax:
After getting this to work fairly reliably, I have run into a situation where the CosaWirelessReceiver appears to stop receiving data after going out of range and then coming back.
Need to check if the NRF24L01P also has this behaviour.
@sirhax
The Cosa NRF24L01P driver works as expected and does not show this behaviour. Message are retransmitted until the retransmit limit(15) is exceeded and then flushed. Getting back into range starts up the transmission/ack again without any problems.