Pages: 1 ... 7 8 [9] 10 11 ... 31   Go Down
Author Topic: Cosa: An Object-Oriented Platform for Arduino programming  (Read 93112 times)
0 Members and 1 Guest are viewing this topic.
Sweden
Offline Offline
Sr. Member
****
Karma: 11
Posts: 465
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

In the latest update of Cosa the focus has been to improve the 1-Wire and DS18B20 device driver with regard to functionality, abstraction and performance.

1. Reducing the need to send rom address when only a single device is connected or issue DS18B20 convert request to multiple devices at the same time (broadcast).
Code:
 // Broadcast convert request to connected devices; 12-bit conversion delay and parasite power
  DS18B20::convert_request(&owi, 12, true);

  // Read back results
  indoors.read_scratchpad();
  outdoors.read_scratchpad();
  basement.read_scratchpad();
The details: Instead of send a match rom command followed by the convert request to each device only a single skip rom and convert request is sent. The performance increase is in the range of several milliseconds per connected device.

2. New iterator class for alarm search. This makes it really easy to check for devices with alarms. The snippet below iterates connected DS18B20 devices and prints devices with alarms (latest temperature convert exceeding thresholds). The temperature is automatically read by the iterator on alarm.
Code:
 DS18B20::convert_request(&owi, 12, true);
  DS18B20::Search iter(&owi);
  DS18B20* temp;
  while ((temp = iter.next()) != 0) {
    trace << PSTR("ALARM:") << *temp << endl;
  }
Typical output (in test):
Code:
ALARM:indoors = 30.37
ALARM:basement = 30.25
See full example sketch at https://github.com/mikaelpatel/Cosa/blob/master/examples/OWI/CosaDS18B20/CosaDS18B20.ino.

3. Support alarm search and dispatch, e.g. callback to device virtual method. This takes the alarm search to the next level and performs all the necessary housekeeping. Application writers "only" need to write code for the alarm situation, i.e., code for the on_alarm() callback method.
Code:
// Simple alarm callback handler
class Thermometer : public DS18B20 {
public:
  Thermometer(OWI* owi, const char* name) : DS18B20(owi, name) {}
  virtual void on_alarm();
};

void
Thermometer::on_alarm()
{
  // Read and print temperature. Do not need reset and presence pulse
  read_scratchpad(false);
  trace << PSTR("ALARM:") << *this << endl;
}
...
void loop()
{
  // Do alarm dispatch; Calls on_alarm() for each device with alarm set
  DS18B20::convert_request(&owi, 12, true);
  owi.alarm_dispatch();
  SLEEP(2);
}
https://github.com/mikaelpatel/Cosa/blob/master/examples/OWI/CosaDS18B20alarm/CosaDS18B20alarm.ino

4. Full support for parasite power even when using broadcast convert request as above.

5. Implements all 1-Wire and DS18B20 functions with naming from the protocol and product description. This is a new design and implementation from scratch.

 Documentation at http://dl.dropboxusercontent.com/u/993383/Cosa/doc/html/da/dc6/classDS18B20.html#pub-methods. And source code at https://github.com/mikaelpatel/Cosa/blob/master/Cosa/OWI/Driver/DS18B20.hh and https://github.com/mikaelpatel/Cosa/blob/master/Cosa/OWI.hh

Cheers!
« Last Edit: June 30, 2013, 04:22:50 pm by kowalski » Logged

Sweden
Offline Offline
Sr. Member
****
Karma: 11
Posts: 465
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

A new Cosa blog post is available. It presents the Cosa LCD device drivers and abstraction.

http://cosa-arduino.blogspot.se/2013/07/object-oriented-lcd-management.html

Cheers!
Logged

Offline Offline
Jr. Member
**
Karma: 2
Posts: 59
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Nice progress again mr Kowalski  smiley-razz

1. Reducing the need to send rom address when only a single device is connected or issue DS18B20 convert request to multiple devices at the same time (broadcast).
Code:
 // Broadcast convert request to connected devices; 12-bit conversion delay and parasite power
  DS18B20::convert_request(&owi, 12, true);

  // Read back results
  indoors.read_scratchpad();
  outdoors.read_scratchpad();
  basement.read_scratchpad();

I haven't used DS18B20's before, but if you are not using rom addresses, how can you tell which sensor is which (ie indoors, outdoors, basement) ??

And then for something else.
I discovered that what I would like to 'invent' for addressing I/O pins was already build by someone else, YOU  smiley-twist

So now I'm exploring your Pin design and have some questions:
  • The base class is the Pin
  • Then there is an InputPin and an OutputPin, but also an AnalogPin. Why is this AnalogPin not an InputPin?
  • The AnalogPin does have an on_change() method, but the digital InputPin doesn't, why?

And then some for the interrupt handling & use of those interrupts:
  • The External and PinChange Interrupts are modelled as an InputPin. No problem with that, but why the difference between External and PinChange interrupts?
  • The reason for the above one is this: I have boards that sometimes have the INT pin wired to a hardware int, and sometimes to another pin (ie pinchange). I would like my classes just to respond to an interrupt, regardless of the fact if it is hardware or pinchange...

And in line with the above:
You seem to make a difference between SPI/SoftSPI, TWI/SoftTWI. That is logical, but some of the devices seem to be hardwired to the SPI driver if I'm not mistaken, ie you can't just have the same sensor/device either (or both) talk over SoftSPI and SPI?? Or is it possible to pass the actual SPI device to the sensor/device?
Logged

Sweden
Offline Offline
Sr. Member
****
Karma: 11
Posts: 465
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Tons of questions! See if I can answer them.

I haven't used DS18B20's before, but if you are not using rom addresses, how can you tell which sensor is which (ie indoors, outdoors, basement) ??
The Cosa OWI interface allows several ways to handle the rom address but I guess that you are concerned with the rom address not being a parameter. The Cosa OWI has two parts; the OWI bus and the OWI device driver. The OWI bus knows about communication while the OWI device driver is a device on the bus. It holds its rom address. It can obtain the address as a parameter to the instance (typically from EEMEM) or by connecting to device using the search command. In this case an index is used. To use this you need to order the devices according to their rom addresses on the wire.

So now I'm exploring your Pin design and have some questions:
  • The base class is the Pin
  • Then there is an InputPin and an OutputPin, but also an AnalogPin. Why is this AnalogPin not an InputPin?
  • The AnalogPin does have an on_change() method, but the digital InputPin doesn't, why?
Hum, Pin is actually an input pin to avoid multiple inheritance. So AnalogPin can be used for digital input. And the Board pin definitions for analog pins is accepted for both InputPin and OutputPin.

The on_change() method has to do with the ISR-Event Handler and is not an observer pattern. If that is what you are asking for? There is an analog conversion completed interrupt. All pins cannot generate pin change interrupts (as I understand the hardware). And there are only a very limited number of pins for external interrupts.

The most important aspect of the Pin class hierarchy is actually performance and abstraction. The Wiring function library is a very slow design and implementation. And not very object-oriented. It is also very difficult to scale to larger designs. There is a lot of calculations and lookups that are done for every digitalRead/Write that are unnecessary. This can be cached on initialization or even better at compile time. There are a few attempts to use templates instead of instances for modeling the hardware resources. Basically code generating each pin instance. This give even higher performance.

I have used some of these techniques for the Cosa Queue, IOBuffer and Offscreen Canvas. Great performance improvements ;-)
And then some for the interrupt handling & use of those interrupts:
  • The External and PinChange Interrupts are modelled as an InputPin. No problem with that, but why the difference between External and PinChange interrupts?
  • The reason for the above one is this: I have boards that sometimes have the INT pin wired to a hardware int, and sometimes to another pin (ie pinchange). I would like my classes just to respond to an interrupt, regardless of the fact if it is hardware or pinchange...
The difference is in the hardware and how pin changes are detected in for instance power down. The next item I regard to be a configuration problem and in Cosa I see that as how you instantiate objects and inherit from classes. Actually from the application perspective it is an Interrupt Handler which is the common super class for both interrupt types (external/pin change). I see that as a modeling aspect. There are several approaches to this.

And in line with the above:
You seem to make a difference between SPI/SoftSPI, TWI/SoftTWI. That is logical, but some of the devices seem to be hardwired to the SPI driver if I'm not mistaken, ie you can't just have the same sensor/device either (or both) talk over SoftSPI and SPI?? Or is it possible to pass the actual SPI device to the sensor/device?
SPI and TWI is work in progress as I would like to allow multiple SPI/TWI bus managers and both software and hardware at the same time. Right now these are singletons (global variable) and may be redefined depending on the application. Drivers only know about the "symbol". This is up to debate as there are other ways to model this relationship. Also allowing both software and hardware version would be nice given a common interface. SPI and TWI do not follow the delegation pattern that I have used in much of the design. They might evolve in this direction ;-) it would give a more flexible design.
BW, Cosa does not include a Soft TWI right now and the Soft SPI is MOSI only. Plenty of work to do in that area. But still the SPI and TWI handling with iovec is a quantum leap forward compare to what is in the Arduino IDE box. Writing drivers becomes so much easier ;-)

Cheers!
« Last Edit: July 03, 2013, 04:52:47 pm by kowalski » Logged

Offline Offline
Jr. Member
**
Karma: 2
Posts: 59
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

The Cosa OWI interface allows several ways to handle the rom address but I guess that you are concerned with the rom address not being a parameter. The Cosa OWI has two parts; the OWI bus and the OWI device driver. The OWI bus knows about communication while the OWI device driver is a device on the bus. It holds its rom address. It can obtain the address as a parameter to the instance (typically from EEMEM) or by connecting to device using the search command. In this case an index is used. To use this you need to order the devices according to their rom addresses on the wire.

Ok, clear! If I check the address on forehand, and connect them in that order everything will be allright...

Quote
The on_change() method has to do with the ISR-Event Handler and is not an observer pattern. If that is what you are asking for? There is an analog conversion completed interrupt. All pins cannot generate pin change interrupts (as I understand the hardware). And there are only a very limited number of pins for external interrupts.

Aha, now I understand. I was just looking at similarities and dissimilarities in the classes while trying to understand how they are setup.

Quote
The difference is in the hardware and how pin changes are detected in for instance power down. The next item I regard to be a configuration problem and in Cosa I see that as how you instantiate objects and inherit from classes. Actually from the application perspective it is an Interrupt Handler which is the common super class for both interrupt types (external/pin change). I see that as a modeling aspect. There are several approaches to this.

I understand the difference now in hardware and pin change interrupts. I have got cases though where the power down behaviour is not important: I just want to register on an interrupt and it is not important if it is hardware or pin change. But you are right about the interrupt handler: class is called by on_interrupt().

Quote
SPI and TWI is work in progress as I would like to allow multiple SPI/TWI bus managers and both software and hardware at the same time. Right now these are singletons (global variable) and may be redefined depending on the application. Drivers only know about the "symbol". This is up to debate as there are other ways to model this relationship. Also allowing both software and hardware version would be nice given a common interface. SPI and TWI do not follow the delegation pattern that I have used in much of the design. They might evolve in this direction ;-) it would give a more flexible design.
BW, Cosa does not include a Soft TWI right now and the Soft SPI is MOSI only. Plenty of work to do in that area. But still the SPI and TWI handling with iovec is a quantum leap forward compare to what is in the Arduino IDE box. Writing drivers becomes so much easier ;-)

Didn't realize that it was still a work in progress, but it explains why I couldn't find some of the Soft parts.
I just thought I didn't understand your code (I'm not a C/C++ expert!).
As I'm using some RTOS, the separation between driver & device is very important. More even if they share the same bus: in that case I need synchronization to allow only one of the devices to be active on the bus. And a separate 'driver' (or device, or bus, depending on how you name things) does make this very, very easy.

Is iovec btw also possible for the 'soft' versions of SPI/TWI, as it relies on interrupts??

And as a side effect of your answers I looked into design patterns and found out that I'm using them without knowing smiley-eek
Logged

Heemskerk, Netherlands
Offline Offline
Sr. Member
****
Karma: 10
Posts: 403
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

I tried the blink program on 1.0.5. Compiles and works great. I tried the same in ECLIPSE but that did not go quite right yet.

I get these errors:
Code:
D:\Arduino\hardware\arduino\cores\arduino/Cosa/IOStream.hh:59: error: expected identifier before '(' token
D:\Arduino\hardware\arduino\cores\arduino/Cosa/IOStream.hh:102: error: expected identifier before '(' token
D:\Arduino\hardware\arduino\cores\arduino/Cosa/IOStream.hh:175: error: expected identifier before '(' token
D:\Arduino\hardware\arduino\cores\arduino/Cosa/IOStream.hh:236: error: expected identifier before '(' token
D:\Arduino\hardware\arduino\cores\arduino/Cosa/IOStream.hh: In member function 'virtual int IOStream::Filter::fputc(char, int*)':
D:\Arduino\hardware\arduino\cores\arduino/Cosa/IOStream.hh:177: error: invalid conversion from 'int' to 'int*'
D:\Arduino\hardware\arduino\cores\arduino/Cosa/IOStream.hh:177: error:   initializing argument 2 of 'virtual int IOStream::Device::fputc(char, int*)'
D:\Arduino\hardware\arduino\cores\arduino/Cosa/IOStream.hh: In member function 'virtual int IOStream::Filter::fgetc(int*)':
D:\Arduino\hardware\arduino\cores\arduino/Cosa/IOStream.hh:238: error: invalid conversion from 'int' to 'int*'
D:\Arduino\hardware\arduino\cores\arduino/Cosa/IOStream.hh:238: error:   initializing argument 1 of 'virtual int IOStream::Device::fgetc(int*)'
D:\Arduino\hardware\arduino\cores\arduino/Cosa/IOStream.hh: In member function 'void IOStream::print(char)':
D:\Arduino\hardware\arduino\cores\arduino/Cosa/IOStream.hh:380: error: no matching function for call to 'IOStream::Device::fputc(char&, __file*&)'
D:\Arduino\hardware\arduino\cores\arduino/Cosa/IOStream.hh:59: note: candidates are: virtual int IOStream::Device::fputc(char, int*)
D:\Arduino\hardware\arduino\cores\arduino/Cosa/IOStream.hh: In member function 'void IOStream::println()':
D:\Arduino\hardware\arduino\cores\arduino/Cosa/IOStream.hh:408: error: no matching function for call to 'IOStream::Device::fputc(char, __file*&)'
D:\Arduino\hardware\arduino\cores\arduino/Cosa/IOStream.hh:59: note: candidates are: virtual int IOStream::Device::fputc(char, int*)

Any ideas?
Logged

Sweden
Offline Offline
Sr. Member
****
Karma: 11
Posts: 465
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Hi nicoverduin. My guess is that the macro putchar/getchar from stdio.h is included in the ECLIPSE/AVR environment. I have added two undef in IOStream.hh:
Code:
#undef putchar
#undef getchar
This has to be repeated in sketches that include IOStream as the Arduino preprocessor is adding some code.

I have not yet used the Arduino ECLIPSE environment. Would be great to have that working. Thanks for trying it out.

Cheers!

BW: After grep-ing through the Arduino core stdio.h is included there in several files. It must be the Arduino pre-processor that includes it:
Code:
HardwareSerial.cpp:#include <stdio.h>
Print.cpp:#include <stdio.h>
Print.h:#include <stdio.h> // for size_t
WInterrupts.c:#include <stdio.h>
wiring_private.h:#include <stdio.h>
« Last Edit: July 05, 2013, 04:02:05 pm by kowalski » Logged

Heemskerk, Netherlands
Offline Offline
Sr. Member
****
Karma: 10
Posts: 403
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Just put the 2 undefs in and it compiles like charm. Lot warnings though in the Arduino compile
about uninitialized variables in program code etc.
But the program works smiley
I'll try some more complicated programs later this week. Not now. Too nice weather het in Holland smiley
Logged

Sweden
Offline Offline
Sr. Member
****
Karma: 11
Posts: 465
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

A new Cosa blog post is available. It describes how to use the event-driven keypad handler for the LCD Keypad Shield.

http://cosa-arduino.blogspot.se/2013/07/event-driven-lcd-keypad-handler.html

Cheers!
« Last Edit: July 07, 2013, 03:50:42 pm by kowalski » Logged

Offline Offline
Jr. Member
**
Karma: 2
Posts: 59
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

See my latest post on weird problems while trying to compile Cosa with Arduino 1.05 and 1.52...
« Last Edit: July 09, 2013, 03:07:41 pm by MarsWarrior » Logged

Sweden
Offline Offline
Sr. Member
****
Karma: 11
Posts: 465
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Hi MarsWarrior.

Quote
Something weird is happening.
I'm trying out Code::Blocks, which gives me alot of troubles (compiler errors, not finding header files etc.).

So I tried the Cosa examples: don't build either.
Then I tried the Arduino IDE 1.05 with Cosa examples: Don't build either (!!!!)
If I read this correctly, you are asking for support with an alternative IDE, Code::Blocks? I haven't used that IDE so it is difficult for me to give any specific advice more than google and read the installation guide. Seems an interesting IDE though.

http://forum.arduino.cc/index.php?topic=145397.0

The problems you are having with Arduino-1.0.5 I guess are related to that you have not installed Cosa for that version? The compiler error messages indicate that the compiler could not file the include files for Cosa in the include path.

Cheers!
« Last Edit: July 09, 2013, 02:43:56 pm by kowalski » Logged

Offline Offline
Jr. Member
**
Karma: 2
Posts: 59
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Just read the PM, and see that I mixed up my question/problem.

Just forget me mentioning Code::Blocks  smiley-kiss, not asking you to support any other IDE than the mighty Arduino IDE  smiley-lol

This is what I did to reproduce the problem:
  • I re-installed Arduino 1.05 and 1.52, just to be save.
  • Then I downloaded the latest Cosa library.
  • I tried to add the Cosa library using the Arduino IDE (Add Library), no luck (java.io.FileNotFoundException: C:\Users\Marco\AppData\Local\Temp\arduino_962622\Cosa10898\Cosa\Cosa\BCD.h (Het systeem kan het opgegeven pad niet vinden)
    )
    I have absolutely no idea what the problem is. Never had this with other libraries...
  • Then I copied the Cosa library manually to my home folder/Arduino/libraries and tried to compile one of the examples: no luck, hh files not found
  • Then I copied the Cosa library manually to the Arduino libraries folder (C:/Program files (x86)/...), same problem, won't compile

Note that the Cosa examples do show up in the Arduino Examples menu and in the sketches / libraries menu! So the Arduino IDE does see Cosa!!

But while trying to compile the CosaBenchMarkPins.ino (or any other example for that matter):
Code:
CosaBenchmarkPins.ino:33:24: error: Cosa/Pins.hh: No such file or directory
CosaBenchmarkPins.ino:34:23: error: Cosa/RTC.hh: No such file or directory
CosaBenchmarkPins.ino:35:25: error: Cosa/Memory.h: No such file or directory
CosaBenchmarkPins.ino:36:28: error: Cosa/Watchdog.hh: No such file or directory
CosaBenchmarkPins.ino:37:25: error: Cosa/Trace.hh: No such file or directory
CosaBenchmarkPins.ino:38:40: error: Cosa/IOStream/Driver/UART.hh: No such file or directory
CosaBenchmarkPins:40: error: 'InputPin' does not name a type
CosaBenchmarkPins:41: error: 'OutputPin' does not name a type
CosaBenchmarkPins:42: error: 'OutputPin' does not name a type
CosaBenchmarkPins:43: error: 'OutputPin' does not name a type
CosaBenchmarkPins:44: error: 'AnalogPin' does not name a type
CosaBenchmarkPins.ino: In function 'void setup()':
CosaBenchmarkPins:53: error: 'uart' was not declared in this scope
CosaBenchmarkPins:54: error: 'trace' was not declared in this scope

When I however use #include <> instead of #include "", the No Such file or directory errors disappear, but still the rest of the errors keep coming...

I'm out of ideas on what is wrong...

Hope you now understand what I did, and what my problem is!
« Last Edit: July 09, 2013, 03:24:45 pm by MarsWarrior » Logged

Sweden
Offline Offline
Sr. Member
****
Karma: 11
Posts: 465
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Hi MarsWarrior.

You really don't like reading documentation ;-). I was under the impression that you had already installed Cosa previously and was now attempting to use it with Code::Blocks and a new version of Arduino. I understand now that this assumption was wrong. Sorry about that.

Cosa is not an Arduino library. The Arduino preprocessor cannot handle sub-directories within a library. I like to structure things so the include is "Cosa/XXX.hh" for header file and then there is even more structure like "Cosa/LCD.hh" and "Cosa/LCD/Driver/HD44780.hh".

Now how can we get the Arduino preprocessor (compiler include path) to recognize this? We put the Cosa directory into the arduino header/source directory! So the installation procedure is:

1. Download Cosa as a zip file.
2. Unzip in your libraries folder in your sketches folder.
3. Move the Cosa (source/header) folder to the Arduino source/header folder. For 1.0.5 that is the folder "arduino-1.0.5/hardware/arduino/cores/arduino".

You havn't done step 3 yet. That's all.

Cheers!

Links to the installation procedure:
1. http://forum.arduino.cc/index.php?topic=150299.0
2. http://cosa-arduino.blogspot.se/2013/02/installing-cosa.html
3. https://github.com/mikaelpatel/Cosa (See section Install)
Logged

Rapa Nui
Offline Offline
Edison Member
*
Karma: 60
Posts: 2086
Pukao hats cleaning services
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

A small remark to that setup - when not working with Cosa the build of a sketch takes ages as it builds all the Cosa stuff as well. How to switch it off ? (without removing the Cosa folder) smiley
Logged

Sweden
Offline Offline
Sr. Member
****
Karma: 11
Posts: 465
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

A small remark to that setup - when not working with Cosa the build of a sketch takes ages as it builds all the Cosa stuff as well. How to switch it off ? (without removing the Cosa folder) smiley
I would suggest using a separate Arduino installation for the Cosa stuff until the Arduino IDE learns how to use library files (archives). I believe this is the root cause to the build problem. It would be even better if Arduino could have library files with directory structure as Java jar-files as this would avoid an old C/C++ archive problem. This would require some new AVR GNU binutil stuff.

Cheers!
Logged

Pages: 1 ... 7 8 [9] 10 11 ... 31   Go Up
Jump to: