Cosa: An Object-Oriented Platform for Arduino programming

Hey kowalski. Great to see you are still plugging away at this project!!

I just purchased the same CC1101 modules as you (http://www.ebay.com/itm/2pcs-CC1101-433MHz-Wireless-Transceiver-Module-NRF905SI4432-with-SMA-Interface-/221274129252) and am wondering if they are usable with the AtTiny85 chips? Seeing "#if !defined(ARDUINO_TINYX5)" at the top of the CC1101.hh/cpp files leads me to believe they might not be?

If they are compatible, what pins get connected between the CC1101 modules at the Tiny85?

Thanks in advance for any assistance!!

Hi sirhax!

Yes the project is still going strong and there is a lot more that I would like to add and achieve. The CC1101 module you have found is exactly what I am using in my prototyping. It works fine as a replacement for the NRF24L01+ module on for instance the Arduino Nano IO Shield.

Right now I have removed the usage of ATtiny85 as the pin D2 is both the USI/SPI clock (SCK) and external interrupt (EXT0). This is possible to solve by using a Pin Change Interrupt (PCI-pin) or simply removing the interrupt handler for ATtiny85. Need to push this onto the backlog (issue list) and figure out a priority for this update. Actually the same goes for NRF24L01+.

You might want to have a look at the ongoing work on the protocol; Cosa Rete. This will become Cosa's version of the panstamp SWAP protocol and work on all Cosa Wireless drivers (RF433, CC1101 and NRF24L01+), and support low power nodes out of the box. Cosa Rete is a scaled down version of SNMP with a dash of DDS (OMG Data Distribution Service). Cosa Wireless interface is one of the building blocks. The other building block is Cosa Registry which acts as a MIB with mapping to application data. The vision is a framework for very easy implementation of low power wireless sensor/actuator nodes.

Cheers!

Ref:

  1. https://github.com/mikaelpatel/Cosa/blob/master/RETE.txt
  2. https://github.com/mikaelpatel/Cosa/blob/master/cores/cosa/Cosa/Rete.hh
  3. Cosa/Wireless.hh at master · mikaelpatel/Cosa · GitHub
  4. https://github.com/mikaelpatel/Cosa/blob/master/cores/cosa/Cosa/Registry.hh
  5. https://github.com/mikaelpatel/Cosa/blob/master/examples/Sandbox/CosaRegistry/CosaRegistry.ino
  6. Simple Network Management Protocol - Wikipedia
  7. Management information base - Wikipedia
  8. Data Distribution Service - Wikipedia

Thanks for the reply, kowalski!

That makes sense. For now I just ordered a handful of "ATTINY84A-PU-ND"s from digikey.

That's certainly some very cool and interesting work! I'm anxious to see it in its final form :).

Along the lines of "internet-of-things", have you seen this project?
http://www.kickstarter.com/projects/flutterwireless/flutter-20-wireless-arduino-with-half-mile-1km-ran

sirhax:
Along the lines of "internet-of-things", have you seen this project?
http://www.kickstarter.com/projects/flutterwireless/flutter-20-wireless-arduino-with-half-mile-1km-ran

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 :wink:

Cheers!

Some news on the latest developments in Cosa. The theme has been supporting multi-DOF boards and improving TWI sensor drivers.

  1. New TWI driver for L3G4200D Digital Gryposcope.
    https://github.com/mikaelpatel/Cosa/blob/master/cores/cosa/Cosa/TWI/Driver/L3G4200D.hh

  2. New TWI driver for MPU6050 Motion Processing Unit; Digital thermometer, accelerometer and gyroscope.
    https://github.com/mikaelpatel/Cosa/blob/master/cores/cosa/Cosa/TWI/Driver/MPU6050.hh

  3. Major refactoring and improvement of the TWI drivers for BMP085 and ADXL345.

  4. Improved TWI scanner. Will print name and short description of connected devices. Verifies identity register (WHO_AM_I) if available. See CosaTWIscanner. https://github.com/mikaelpatel/Cosa/blob/master/examples/TWI/CosaTWIscanner/CosaTWIscanner.ino

device = 0x1e:group = 3.6:HMC5883L, 3-Axis Digital Compass
device = 0x53:group = 10.3:ADXL345, Digital Accelermeter
device = 0x69:group = 13.1:L3G4200D, 3-Axis Digital Gyroscope
device = 0x77:group = 14.7:BMP085, Digital Pressure Sensor

Above is the scanner information generated for the GY-80.

  1. Extended example sketch for GY-80 10DOF module.
Cosa10DOF: started
free_memory() = 1499
sizeof(TWI::Driver) = 3
sizeof(ADXL345) = 3
sizeof(BMP085) = 37
sizeof(HMC5883L) = 13
sizeof(L3G4200D) = 3
acceleratometer.begin() = 1
bmp.begin(BMP085::ULTRA_LOW_POWER) = 1
gyroscope.begin() = 1
compass.begin() = 1
ADXL345(x = 260, y = 2, z = 2)
BMP085(temperature = 222, pressure = 98462)
HMC5883L(x = -579, y = 36, z = -143)
L3G4200D(x = -43, y = 216, z = 3)

ADXL345(x = 258, y = 0, z = 0)
BMP085(temperature = 222, pressure = 98459)
HMC5883L(x = -579, y = 18, z = -143)
L3G4200D(x = -53, y = 204, z = 15)

ADXL345(x = 260, y = 0, z = 0)
BMP085(temperature = 221, pressure = 98451)
HMC5883L(x = -579, y = -4, z = -143)
L3G4200D(x = -9, y = 197, z = -4)
  1. Wireless IOStream class. Use any Wireless driver as an IOStream. The below example sketch will send digital and analog pin readings over the connected wireless driver and display on an LCD (monitor).
    Cosa/CosaWirelessIOStream.ino at master · mikaelpatel/Cosa · GitHub
    Cosa/CosaWirelessMonitor.ino at master · mikaelpatel/Cosa · GitHub
    Cheers!

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;
  }
  // Calculate and print values
  trace << PSTR("BMP085(mode = ") << mode
	<< PSTR(", temperature = ") << bmp.get_temperature()
	<< PSTR(", ABS pressure = ") << bmp.get_ABS_pressure()
	<< PSTR(", BSL pressure = ") << bmp.get_BSL_pressure(235, bmp.get_ABS_pressure())
	<< PSTR(", delay = ") << (stop - start)
	<< PSTR(")") << endl;
BMP085(mode = 1, temperature = 238, ABS pressure = 97811, BSL pressure = 100581, delay = 32)

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).

@pito

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.

Cheers!

Hey Kowalski,
I'm having trouble getting the CC1101 transceivers to work, and am hoping that you can offer some assistance :). Here's my setup:

I have an UNO R3 running CosaWirelessReceiver and a Mega2560 running CosaWirelessSender.

I commented out the two NRF24 lines and uncommented the CC1101 lines in both programs as follows:

#include "Cosa/Wireless/Driver/CC1101.hh"
CC1101 rf(0xC05A, 0x01);

// #include "Cosa/Wireless/Driver/NRF24L01P.hh"
// NRF24L01P rf(0xC05A, 0x01);

Here is how I have the boards/chips wired up:

CC1101   UnoPin# MegaPin#
1:GND    GND     GND
2:3.3v   3.3v    3.3v
3:CE     9       48
4:CSN    10      53
5:SCK    13      52
6:MOSI   11      51
7:MISO   12      50
8:IRQ    2/EXT0  21/EXT0

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?

Thanks!

@sirhax

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.

Try the default setting with IRQ connected to D2.

Cheers!

Thanks for the response, Kowalski!

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.

Cheers!

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).

Cheers!

Resources:

  1. Installing Cosa, Cosa: Installing Cosa
  2. Github, GitHub - mikaelpatel/Cosa: An Object-Oriented Platform for Arduino/AVR
  3. On-line documentation, http://dl.dropboxusercontent.com/u/993383/Cosa/doc/html/index.html

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? :slight_smile:

pito:
Any port to M0+, M3, M4 or something like that in planning? :slight_smile:

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 .

Cheers!

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 :slight_smile:

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.


Rob

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).

Cheers!

And a HAL might help as well..

Some news on the latest improvements and addition to Cosa:

  1. Update of Cosa Networking Protocol draft (RETE)
    https://github.com/mikaelpatel/Cosa/blob/master/RETE.txt

  2. Added a template class for bitsets. See interface and example sketch.
    Cosa/BitSet.hh at master · mikaelpatel/Cosa · GitHub
    Cosa/CosaBitSet.ino at master · mikaelpatel/Cosa · GitHub

  3. Support for encoding and decoding Google Protocol Buffers protocol.
    https://github.com/mikaelpatel/Cosa/blob/master/cores/cosa/Cosa/ProtocolBuffer.hh
    https://github.com/mikaelpatel/Cosa/blob/master/examples/Sandbox/CosaProtocolBuffer/CosaProtocolBuffer.ino

Cheers!

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....

Ok maybe it is necessary :slight_smile:


Rob

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...