Offline
Jr. Member
Karma: 1
Posts: 65
|
 |
« Reply #15 on: February 23, 2013, 06:03:06 am » |
Hmm, but can I check a stream for input in a non blocking way?
|
|
|
|
|
Logged
|
|
|
|
|
Offline
Jr. Member
Karma: 1
Posts: 65
|
 |
« Reply #16 on: February 23, 2013, 06:22:32 am » |
MyClass * pClass = new MyClass(var1, var2); pClass->Init();
Thanks, that was helpful. A safer way would be to use reference like MyClass & rClass; but this requires that you pass the reference via the constructor. It would be too late in the Init() function.
I do not see a problem with that. As for function pointers, I would rather use derived classes.
Like declaring Menu class based on serial class? (Just learned that Serial is not the class, so maybe it is 'serial'?). But what if the menu wants to read from Serial, but display informations somewhere else and then the errors on...?
|
|
|
|
|
Logged
|
|
|
|
|
Temple, Texas
Offline
Sr. Member
Karma: 14
Posts: 354
|
 |
« Reply #17 on: February 23, 2013, 08:20:22 am » |
@OutOfLine Not sure where in this thread it fits, but on the Arduino I usually use the Streaming Library, like this: #include <Streaming> ... Serial << "Hello there " << ", i= " << i << endl; ...
And then when I compile for various reasons on another platform I use: #include <iostream> using namespace std; ostream & Serial = cout;
... so now I can use throughout, the same
Serial << "Hello there " << ", i= " << i << endl;
Cheers, John
|
|
|
|
|
Logged
|
|
|
|
|
Offline
Jr. Member
Karma: 1
Posts: 65
|
 |
« Reply #18 on: February 23, 2013, 09:00:57 am » |
@johncc: Thank you for the nice hint, will try it later on.
|
|
|
|
|
Logged
|
|
|
|
|
Finland
Offline
Jr. Member
Karma: 1
Posts: 84
|
 |
« Reply #19 on: February 23, 2013, 03:33:28 pm » |
Like declaring Menu class based on serial class? (Just learned that Serial is not the class, so maybe it is 'serial'?).
But what if the menu wants to read from Serial, but display informations somewhere else and then the errors on...?
Serial port are instantiated from a class already, so it's not necessary to derive from them. For example, from Arduino reference: "All Arduino boards have at least one serial port (also known as a UART or USART): Serial." "The Arduino Leonardo board uses Serial1 to communicate via RS232 on pins 0 (RX) and 1 (TX). Serial is reserved for USB CDC communication." Anyways, if I'm reading this correctly, it looks like the instantiation is done in HardwareSerial.cpp/.h from a class named HardwareSerial into instances Serial, Serial1, and so on. This is included from Arduino.h so, at least you can trust that they are always accessible hardware supporting.. Since the Serial classes are already instantiated in memory, you should just pass the related instances by reference to save memory unless you insist on overriding some functions like read and write. Outside Arduino IDE this probably works in a different way. However, my point about function pointers was that it kinda doesn't belong in C++ when you have other neater ways of doing the same thing in my opinion. Function pointers are typically used in C when you need to collect actions in an array and pass them into function calls. Nothing stops you from doing the same within a class though. It's a separate topic from above because I don't see what would the passed function be.
|
|
|
|
|
Logged
|
|
|
|
|
Offline
Jr. Member
Karma: 1
Posts: 65
|
 |
« Reply #20 on: February 24, 2013, 04:05:05 am » |
I experimented with your suggestions, wrote a stub for the menu just as a simple test if I can use serial I/O from both, the Menu class *and* the Arduino sketch. It worked right ahead, and like always afterwards you cannot understand why I didn't get that right first time... Didn't I try about the same thing as one of my first test? Well obviously not *exactly* the same  /* stub.ino Confused about passing I/O functions from the sketch to the menu class I wrote this TestStub class to make some very basic I/O tests. Based on insights and suggestions from a discussion in Arduino forums. Special thanks to Nick Gammon, Chaul, johncc. */
/* **************************************************************** */ /* Library: */
class TestStub { public: TestStub(Stream & port, int (*maybeInput)(void)) : port_ (port), maybe_input(maybeInput) { }
// Basic tests for menu output: void out(const char *str) { port_.print(str); }
// Testing overloading out(): void out(const char c) { port_.print(c); } void out(const int i) { port_.print(i); }
// Some basic output functions: void ln() { port_.print('\n'); } void tab() { port_.print('\t'); }
bool lurk() { /* int maybe_input() must be a function returning one byte data or if there is no input returning EOF */ int INP=(*maybe_input)();
if ( INP != EOF ) { // there *is* input out("Lurker sees input:\t"); out((char) INP); // I don't care about newline here ;) tab(); out(INP); ln();
return true; } return false; }
private: Stream & port_; int (*maybe_input)(void); // maybe_input() Must return EOF or next char };
/* **************************************************************** */ /* Arduino program: */
int men_input() { // men_input() Must return EOF or next char if (!Serial.available()) return EOF;
return Serial.read(); }
TestStub STUB(Serial, &men_input);
void setup() { Serial.begin(115200); STUB.out("Basic c++ I/O test...\tTesting maybe_input(), string out(), lurk():\n"); }
long cnt=0;
void loop() { STUB.lurk(); // lurks for input, then trolls.
// Test if I can still call Serial.print() from main(): if (! (cnt++ % 100000L)) { Serial.print("Serial.print() from main().\t"); Serial.println(cnt -1); } }
/* **************************************************************** */
Changing existing git code to this implementation should be straight ahead. I hope to do that today. Thanks a lot for all the input.
|
|
|
|
|
Logged
|
|
|
|
|
Offline
Jr. Member
Karma: 1
Posts: 65
|
 |
« Reply #21 on: February 24, 2013, 09:14:17 am » |
Well, yes changing the existing git code to this implementation was quick, but... it gave the same re-definition problems as before  After a lot of trying this&that turns out that it (probably) was some #include logic, like not having loaded Arduino.h in a file when I thought I had, resulting in names changing meaning while compiling or similar. Starts working now on Arduino. I still have some details to chew on: * PROGMEM strings I have used them so far for constant strings in the user interface. Things would get easier if I could drop them (without using RAM) I have read that they could be replaced by string constants. Searching a bit does not sound so simple. If I *only* use them for string output functions it seems a save bet that the compiler would optimize them away. Is that true? * How can I use (test) the code on the PC? (Linux, in my case). Still not really understanding that stream stuff... What do I #include that it will know 'Stream' on the PC, and what about 'Serial'?
|
|
|
|
|
Logged
|
|
|
|
|
Global Moderator
Melbourne, Australia
Offline
Shannon Member
Karma: 226
Posts: 14101
Lua rocks!
|
 |
« Reply #22 on: February 24, 2013, 02:49:47 pm » |
To use program memory for strings, just use the F macro, as in this modified example: class myMenu { private: Stream & port_; public: myMenu (Stream & port) : port_ (port) { } void begin (); };
void myMenu::begin () { port_.println (F("Menu initialized.")); // <-------- keep string in PROGMEM }
myMenu menu (Serial);
void setup () { Serial.begin (115200); menu.begin (); } // end of setup
void loop () { }
As for testing on the PC, I personally just upload to my board each time. Trying to do stuff on the PC is going to mean getting the libraries included etc.
|
|
|
|
|
Logged
|
|
|
|
|
Offline
Jr. Member
Karma: 1
Posts: 65
|
 |
« Reply #23 on: February 25, 2013, 05:47:45 am » |
@Nick Thank you for all your help. I'd prefer keeping the possibility to compile test code for the PC for a while, if it does not prove to be too difficult. I plan to do some stuff where I will need fast edit-compile-test cycles to find my way through  Still feeling very new to that c++ stuff. I have found a way to have both now, doing an ugly hack called preprocessor magic. I think I will drop that once feeling more comfortable with c++ after doing some more coding. You are right: it *is* a hassle to maintain... Not decided on PROGMEM yet, will do some more tests. F("string") macro is fine for Arduino, but another thing to be taken care of as long as I want to use a PC as test platform. My current version is now online, comments welcome. https://github.com/reppr/pulses
|
|
|
|
« Last Edit: February 25, 2013, 09:39:49 am by OutOfLine »
|
Logged
|
|
|
|
|
Global Moderator
Melbourne, Australia
Offline
Shannon Member
Karma: 226
Posts: 14101
Lua rocks!
|
 |
« Reply #24 on: February 25, 2013, 04:13:21 pm » |
F("string") macro is fine for Arduino, but another thing to be taken care of as long as I want to use a PC as test platform.
Hardly a lot of trouble though, just get the macro to return the original string.
|
|
|
|
|
Logged
|
|
|
|
|
Offline
Jr. Member
Karma: 1
Posts: 65
|
 |
« Reply #25 on: February 26, 2013, 08:56:24 am » |
Hardly a lot of trouble though, just get the macro to return the original string.
True. For strings used *multiple times* I think declaring them as a named constant used only to pass as const parameter to const output functions should produce very similar results as declaring them as PROGMEM. I'm not definitely sure about that yet, though.
|
|
|
|
|
Logged
|
|
|
|
|
Global Moderator
Melbourne, Australia
Offline
Shannon Member
Karma: 226
Posts: 14101
Lua rocks!
|
 |
« Reply #26 on: February 26, 2013, 03:11:03 pm » |
The compiler will do that anyway, I believe. Example: const char * foo = "But does it get goat's blood out?"; const char * bar = "But does it get goat's blood out?";
void setup () { Serial.begin (115200); Serial.println (foo); Serial.println (bar); Serial.println ((int) foo); Serial.println ((int) bar); } // end of setup
void loop () { }
The second pair of lines shows that foo and bar are actually the same string: But does it get goat's blood out? But does it get goat's blood out? 256 256
|
|
|
|
|
Logged
|
|
|
|
|
Offline
Jr. Member
Karma: 1
Posts: 65
|
 |
« Reply #27 on: February 27, 2013, 02:43:45 am » |
Interesting, and a nice trick to test that. I have started some testing too, testing RAM usage and sketch size influence of Arduino F() macro: *Not* using F(): Using Arduino F() macro: Binary sketch size: 7,206 bytes Binary sketch size: 7,534 bytes RAM: 465 RAM: 1525 nice 
|
|
|
|
|
Logged
|
|
|
|
|
Global Moderator
Melbourne, Australia
Offline
Shannon Member
Karma: 226
Posts: 14101
Lua rocks!
|
 |
« Reply #28 on: February 27, 2013, 03:44:32 am » |
Proof?
|
|
|
|
|
Logged
|
|
|
|
|
Offline
Jr. Member
Karma: 1
Posts: 65
|
 |
« Reply #29 on: February 27, 2013, 05:02:13 am » |
Continued testing... Testing RAM usage and sketch size: Using Arduino F() macro *only*, eliminating const strings and all PROGMEM stuff: Binary sketch size: 7,534 bytes RAM: 1685 even better 
|
|
|
|
|
Logged
|
|
|
|
|
|