Show Posts
Pages: 1 [2] 3 4 ... 22
16  Using Arduino / Programming Questions / Re: Use momentary to trigger output for a time w/o using delay? on: December 01, 2012, 09:14:52 pm
This results in turning the LED off immediately after turning it on:

Code:
    buttonState = digitalRead(buttonPin);   //check if the pushbutton is pressed
    Serial.println(buttonState);            //print pushbutton condition to serial monitor
    currentMillis = millis();
    if (buttonState == HIGH) {                            //if pushbutton has been pressed:     
       if (currentMillis - previousMillis > ontime) {     //check if difference between current time       
         digitalWrite(LEDPin, HIGH);                      //and previous time is larger than the alarm time
         previousMillis = currentMillis;       
       }
    }
    digitalWrite(LEDPin, LOW);              //turn LED off

Note that you say "if button is high, set led pin high;" followed by "always set led pin low".  That "always" part (digitalWrite(LEDPin, LOW)) happens on every single loop.  Consider the following instead:

Code:

unsigned int debounceTime = 100;
unsigned long          onTime = 5000;


...


void loop() {

  static bool                     ledOn = false;
  static unsigned long buttonTm = 0;
  static unsigned long      ledTm = 0;

    // always debounce your inputs, but debouncing uses a different time counter
    // than your LED on, necessarily, as you want to be able to press the button
    // more than once every on period

  if( digitalRead(buttonPin) == HIGH && millis() - buttonTm > debounceTime ) {

    buttonTm = millis();

    if( ledOn ) {
        // LED is already on, turn it off
      digitalWrite(LEDPin, LOW);
      ledOn = false;
    }
    else {
       // LED is not on, turn it on
      digitalWrite(LEDPin, HIGH);
      ledOn = true;
      ledTm = millis();
   }
 }

 if( ledOn == true && millis() - ledTm >= onTime ) {
     // LED has been on long enough to turn off automatically
   digitalWrite(LEDPin, LOW);
   ledOn = false;
 }
}

Hope that helps.

 
   
 
17  Using Arduino / Programming Questions / Re: How to specify the size of a class array ? on: December 01, 2012, 08:14:15 pm

I want the user to be able to specify a size. At compile time. Dynamic allocation would mean grow the array as elements are add()ed. String is telling us that kind of functionality is not without problems smiley-wink

A point of note You can't do that with a #define and the Arduino IDE as you intimated earlier.  Only the code in your sketch sees the #define, the library is different compilation unit, and does not see it with the standard arduino make process.  (Unless of course, you ask them to inline your code in their .ino or something.)

!c
18  Using Arduino / Programming Questions / Re: Variation in Hex Size between Windows and OSX on: December 01, 2012, 08:06:49 pm
Can you post the code?

8k LoC and 30+ files?  No. (And its why I didn't post it in programming questions, but it got moved here anyhow.)

I'm asking if anyone is aware of any known deviations between the two environments which would be helpful as I go bit by bit trying to create a minimal reproducible case to identify the culprit.  "No, none are known." Is a perfectly acceptable answer. =)

!c

19  Using Arduino / Motors, Mechanics, and Power / Re: Several motors simultaneously - what is the best strategy? on: December 01, 2012, 01:55:07 pm
Are you dealing with Hobby Servos, which use PWM for positioning control and do not have speed control, or Servos as in brushless DC motors with encoder feedback?

Since you talk about speed control, I'm pretty sure you can't be talking about Hobby servos - or, at least, hobby servos are a poor choice for your application whereas a standard DC brushed motor, stepper, or brushless servo is a better choice.  (A continuous rotation modified hobby servo might as well be a brushed DC motor optimized for torque->size.)

If you're using PWM drivers for dc brushed motors, you can simply analogWrite() the speeds to your PWM output pins, and they'll all move at different rates...  If you modify both the period and the duty cycle, you can achieve lower speeds (measured over a longer time) by increasing the period, with the resulting "rougher" movement than typical PWM, which never sees the motor come to a complete stop.  You can roll your own, or perhaps use one of the PWM libraries of late that let you control both the period and duty cycle.

!c
20  Using Arduino / Programming Questions / Variation in Hex Size between Windows and OSX on: December 01, 2012, 12:42:18 pm
Hi all, I'm noticing that between OSX and Windows distributions of the same version of Arduino (1.0.1), I'm getting a variation in hex size for the same sketch built for Leonardo. 

On OSX, the sketch compiles to 28,542 bytes, but on Windows it compiles to 28,708.  (Which is too large for Leonardo.)  On 1.0.2 the sketch is even larger, but I'll chalk that up to feature bloat.

Is anyone aware of any differences in the core libraries, or the AVR GCC compiler (or its options) between OSX and Windows that would account for the additional 166 bytes of flash usage?

Thanks!

!c
21  Development / Other Software Development / Re: OpenMoCo Menu Manager - completely automated menus for Arduino on: December 01, 2012, 12:26:07 pm
New update released, includes the following:

* Ability to have Bit flag input types, showing "On" and "Off" (allow users to toggle a single bit out of a byte)
* Automatic storage of values to EEPROM (Using OMEEPROM library included)
* Accelerating input changes when button is held (scroll through values faster the longer buttons are held)
* Query the library to determine if button is held, or simply pressed when using it to manage input outside of a menu
* Navigation bug fixes
* Greater flash size efficiency through coding optimizations

It can be downloaded here: http://dynamicperception.com/software/openmoco-avr-libraries
Updated documentation here: http://dynamicperception.com/libdox/OMAVR/class_o_m_menu_mgr.html

!c
22  Development / Other Software Development / Re: OpenMoCo Menu Manager - completely automated menus for Arduino on: November 11, 2012, 10:28:38 am

Problem 1: After download and archive extraction into the libraries folder, the Arduino IDE complains about the root directory name. I had to rename it to something without "-" and ".". I also noticed that there is exactly only one example for the complete lib. Luckily it covers the menu manager, but i would have expected some more examples within the Arduino IDE for other parts of the lib.

Hi Oliver,

What dashes and dots?  There are no dashes or dots in any directory names for any OM libraries?  The OM Menu Manager root directory name is 'OMMenuMgr'.  The example exercises 100% of the OMMenuMgr functions. 

If it's other libraries you're looking for information and examples on, read the doxygen docs which are in docs/html -- there are pages on the more complex libraries, which give many examples of their use, and all other libraries are fully documented with basic examples. 


Problem 2: I do not know how to setup the u8glib picture loop. More specific: I need to draw the screen more than once. The draw callback handler for u8glib is easy. Assuming a font with char width 4 and height 8 it is this:

Code:
void uiDraw(char* p_text, int p_row, int p_col, int len) {
  u8g.setCursorPos(p_col*4, p_row*8); 
  for( int i = 0; i < len; i++ ) {
    if( c < '!' || c > '~' )
      u8g.write(' ');
    else 
      u8g.write(p_text[i]);
  }
}

However, the screen has to be updated several times. But i do not know how to do this. Controll is given to this lib with checkInput(), but i assume that this procedure also does the character output. Pseudocode for u8glib is this:
1. check keys
2. handle keys
3. several times: redraw screen
I looked into the code, but did not find how to do 3)

Any ideas?

Oliver

I don't see from the u8g docs that it needs to be drawn constantly, but instead only to be drawn when it changes.  However, if you want to re-draw constantly, then just store the draw data in global scope, and access that as it updates...

something like this:

Code:
struct {

  char text[OM_MENU_ROWS];
  int row;
  int col;
  int len;
} screenDat;

boolean screenSet = false;

...

void setup() {

  ...

  Menu.setDrawHandler(uiDraw);
  Menu.setExitHandler(uiExit);
}

void loop() {

  Menu.checkInput();

  if( screenSet )
     u8draw();

}

void uiDraw(char* p_text, int p_row, int p_col, int len) {

    // clear out buffer
  memset(screenDat.text, ' ', OM_MENU_ROWS);
  memcpy(&screenDat.text, p_text, len);

  screenDat.row = p_row;
  screenDat.col = p_col;
  screenDat.len = len;
 
  screenSet = true;

}

void uiExit() {

  screenSet = false;
}
23  Development / Other Software Development / Re: OpenMoCo Menu Manager - completely automated menus for Arduino on: November 10, 2012, 10:42:44 am
Hi Oliver, thanks for the list - I hadn't seen m2tklib before, but it looks like we took a very similar approach in most regards.  The online Doxygen documentation was linked in the first post, here it is again: http://dynamicperception.com/libdox/OMAVR/class_o_m_menu_mgr.html 

Thanks!

Chris
24  Development / Other Software Development / Re: OpenMoCo Menu Manager - completed automated menus for Arduino on: November 09, 2012, 02:22:12 pm
Here is a complete example sketch showing everything you need to do to create an advanced menu, with integral input types, select list types, action handlers, and more.  Note the bulk of the work is simply in declaring the menu data elements, the rest of the code is minimal and is fully functional.

Code:
/**  Example OMMenuMgr Sketch

 @author
 C. A. Church
 
 */

#include "OMMenuMgr.h"
#include <LiquidCrystal.h>

 // ======== ui setup ===========
 
    // lcd pins
const byte LCD_RS  = 17;
const byte LCD_EN  = 18;
const byte LCD_D4  = 11;
const byte LCD_D5  = 8;
const byte LCD_D6  = 7;
const byte LCD_D7  = 4;

const byte LCD_ROWS = 2;
const byte LCD_COLS = 16;

 // which input is our button
const byte BUT_PIN = 14;

  // analog button read values
const int BUTSEL_VAL  = 70;
const int BUTFWD_VAL  = 250;
const int BUTREV_VAL  = 450;
const int BUTDEC_VAL  = 655;
const int BUTINC_VAL  = 830;

const byte BUT_THRESH  = 60;

  // mapping of analog button values for menu
const int BUT_MAP[5][2] = {
                         {BUTFWD_VAL, BUTTON_FORWARD},
                         {BUTINC_VAL, BUTTON_INCREASE},
                         {BUTDEC_VAL, BUTTON_DECREASE},
                         {BUTREV_VAL, BUTTON_BACK},
                         {BUTSEL_VAL, BUTTON_SELECT}
                    };
                            


// ====== Test Menu ===========

 // declare some variables we want to modify
byte foo = 0;
byte sel = 0;
unsigned int bar = 1;
long baz  = 0;
float bak = 0.0;

  // Create a list of states and values for a select input
MENU_SELECT_ITEM  sel_ign = { 2, {"Ignore"} };
MENU_SELECT_ITEM  sel_on  = { 1, {"On"} };
MENU_SELECT_ITEM  sel_off = { 0, {"Off"} };

MENU_SELECT_LIST  state_list[] = { &sel_ign, &sel_on, &sel_off };
                                  
  // the special target for our state input
  
                             // TARGET VAR   LENGTH                          TARGET SELECT LIST
MENU_SELECT state_select = { &sel,           MENU_SELECT_SIZE(state_list),   MENU_TARGET(&state_list) };

  // values to use

                    //    TYPE            MAX    MIN    TARGET
MENU_VALUE foo_value = { TYPE_BYTE,       100,   0,     MENU_TARGET(&foo) };
MENU_VALUE bar_value = { TYPE_UINT,       10000, 100,   MENU_TARGET(&bar) };
MENU_VALUE baz_value = { TYPE_LONG,       10000, 1,     MENU_TARGET(&baz) };
MENU_VALUE bak_value = { TYPE_FLOAT_1000, 0,     0,     MENU_TARGET(&bak) };
MENU_VALUE sel_value = { TYPE_SELECT,     0,     0,     MENU_TARGET(&state_select) };

                    //        LABEL           TYPE        LENGTH    TARGET
MENU_ITEM item_checkme  = { {"Byte Edit"},    ITEM_VALUE,  0,        MENU_TARGET(&foo_value) };
MENU_ITEM item_barme    = { {"(Bar) UInt Edit"},     ITEM_VALUE,  0,        MENU_TARGET(&bar_value) };
MENU_ITEM item_bazme    = { {"Long Edit"},    ITEM_VALUE,  0,        MENU_TARGET(&baz_value) };
MENU_ITEM item_bakme    = { {"Float Edit"},   ITEM_VALUE,  0,        MENU_TARGET(&bak_value) };
MENU_ITEM item_state    = { {"Select Input"}, ITEM_VALUE,  0,        MENU_TARGET(&sel_value) };
MENU_ITEM item_testme   = { {"Test Action"},  ITEM_ACTION, 0,        MENU_TARGET(uiQwkScreen) };

                   //        List of items in menu level
MENU_LIST root_list[]   = { &item_checkme, &item_barme, &item_bazme, &item_bakme, &item_state, &item_testme };

                  // Root item is always created last, so we can add all other items to it
MENU_ITEM menu_root     = { {"Root"},        ITEM_MENU,   MENU_SIZE(root_list),    MENU_TARGET(&root_list) };

// ======== Object Initialization ==========


 // initialize LCD object
LiquidCrystal lcd(LCD_RS, LCD_EN, LCD_D4, LCD_D5, LCD_D6, LCD_D7);

 // Initialize Menu Manager
OMMenuMgr Menu(&menu_root);


// ======= Main Code Body =========

void setup() {

  lcd.begin(LCD_COLS, LCD_ROWS);
  
  uiMain();
  
  Menu.setDrawHandler(uiDraw);
  Menu.setExitHandler(uiMain);
  Menu.setAnalogButtonPin(BUT_PIN, BUT_MAP, BUT_THRESH);
  Menu.enable(true);
  
}

void loop() {
 Menu.checkInput();
}

 // draw handler
void uiDraw(char* p_text, int p_row, int p_col, int len) {
  lcd.setCursor(p_col, p_row);
  
  for( int i = 0; i < len; i++ ) {
    if( p_text[i] < '!' || p_text[i] > '~' )
      lcd.write(' ');
    else  
      lcd.write(p_text[i]);
  }
}


 // menu exit handler / main screen draw
void uiMain() {
  
  lcd.clear();
  lcd.setCursor(0, 0);
  lcd.print("Enter for Menu");
  lcd.setCursor(0, 1);
  lcd.print("Bar = ");
  lcd.print(bar, DEC);
}

 // our special action
void uiQwkScreen() {
  lcd.clear();
  Menu.enable(false);
  
  lcd.print("Action!");
  lcd.setCursor(0, 1);
  lcd.print("Enter 2 return");
  
  while( Menu.checkInput() != BUTTON_SELECT ) {
    ; // wait!
  }
  
  Menu.enable(true);
  lcd.clear();
}  
25  Development / Other Software Development / OpenMoCo Menu Manager - completely automated menus for Arduino on: November 09, 2012, 02:21:50 pm
Hi all,

I've created a new release of my OpenMoCo libraries for motion control applications (available here: http://dynamicperception.com/software/openmoco-avr-libraries ), but I wanted to bring attention to a new library included in it: OMMenuMgr, which is a completely automated menuing system for the arduino.

I know there are a number of menuing libraries out there, but none of them met our needs as we have several different projects active, some of which use up to dozens of menu items.  One of the key problems I needed to eliminate were duplicated code in menu handling - such as needing to determine which value is being edited, display it properly, allow temporary edits, and then save it to the final value only when the user chooses to.  Using any existing menu libraries would've required a great deal of code, and provided little advantage for us when the base menu navigation was the easiest part of the project.  Essentially, the only thing this menu system doesn't do for you is draw the characters on the LCD (but it does call your function to do it =)

This is a first release of the library, so obviously it has some limitations, and there may be some warts left to uncover, but for a high-level description:

The OpenMoCo Menu Manager provides a nearly complete automation of a menuing system. This class is designed to allow for rapid development of menuing systems on Arduino devices, using up to five input controls (buttons), and character displays of at least two rows. Designed to make it easy to implement menu systems, the Menu Manager requires the developer to do little more than specify the structure of the menu, and how to draw on the display.

Key features:

   - Menu structures automatically and easily stored in program memory instead of SRAM
   - Automatic handling of either analog or digital button inputs
   - Automatic management of user inputs for numeric and select list types
     --   In-place editing with ability for user to abort
     --   Write-back on user save to original variables
     --   Specify lists of display values for users to select between
     --   Control over user input precision in floats, and more
   - Ability to trigger code actions from menu items
   - One-method polling automatically handles and executes menu as-needed
   - Streamlined setup for complex and even recursive menus
   - Support for any width screen
   - Reduced memory footprint
   - No fixed limitations on menu depths, have as many sub-menus as you require
   - Flexible drawing methodology allows the use of any character-based (or even graphic) display

The Menu Manager displays a character-based menu when triggered by the user. Five user inputs are used (although only four are required): Enter, Up, Down, Back, and Forward. Forward is optional. These inputs may either be buttons tied to digital pins, or up to five buttons tied to a single analog pin using a series of resistors to present different analog values when a button is pressed.

The menu is triggered by hitting the Enter key by the user when the menu is enabled. When it is displayed, the user is presented with all available options at the current menu level, one per row, with a cursor indicating the currently selected item. The up and down keys scroll the list through all available items at the current menu level. If the user presses enter, or forward on the current item, the item will be presented as either a value edit, a new menu, or an action will be executed as defined by the user based on the type of the menu entry. The back button will cancel out of the current input, go back one menu level, or exit the menu entirely if the user is at the root menu level.

When a value is being edited, the user may adjust the value within the range specified by the developer non-destructively using the up and down buttons. The user may cancel the edit of the value by using the back button, or may save the value using either of enter or forward. When the user saves the value, it is written directly to the variable specified by the developer. All numeric types are supported, and special select lists are supported as well. For select lists, the user is presented with strings defined by the developer for the numeric values stored in the target variable, providing the ability to give the user a more complete and obvious solution.

Menu items may also be sub-menus. You can even re-use the same sub-menus under different menus with minimal impact to flash size and SRAM usage, letting you use the same menus under different contexts.

Menu items may be actions - you may wish to draw special screens and allow for use-case driven inputs. In this manner, you can trigger callbacks when menu items are triggered and disable the menu easily while interacting with the user, and then seamlessly place the user back into the menu where they left off when they are done.

Finally, the Menu Manager can be used to easily poll the user inputs without drawing the menu as needed by the developer.


The complete documentation for the menu manager is available here, which covers its capabilities and usage in great detail: http://dynamicperception.com/libdox/OMAVR/class_o_m_menu_mgr.html

The library is available for download as part of the OpenMoCo AVR Libraries here: http://dynamicperception.com/software/openmoco-avr-libraries

I'd love your feedback!  

26  Using Arduino / Programming Questions / Re: LCD Menu Help on: August 22, 2012, 10:20:40 am
A typical way to make something have a different function after some other event occurs, is to record whether the other event has occurred, and then change your behavior based on that signal.

I don't know about the library you're using, but the following pseudo-code should be informative:

Code:

if( buttonPressed ) {
   if( ! alreadyPressed ) {
       alreadyPressed = true;
       showMenu();
   }
   else {
       advanceMenu();
   }
}

if( cancelButtonPressed ) {
   alreadyPressed = false;
   hideMenu();
}

!c
27  Using Arduino / Programming Questions / Re: microsSince() - dealing with the roll over on: August 19, 2012, 04:24:50 pm
...
and the check works after rollover.  Why is the explicit cast to unsigned char necessary?

Because you've changed the domain of the example.  Dealing with millis(), etc. we are dealing with unsigned longs.  You've changed the parameters, and entered into the world of "what the compiler chooses to do to optimize this case," which breaks the rules - because the compiler has not done what you expected.

The following works perfectly fine, as has been known for some time:

Code:
unsigned long counter = 0;
unsigned long start_time = 0;
#define interval 10000000

void setup() {
  Serial.begin(9600);
  for (int x=0; x<1000; x++) { // run through uchar a few times
    counter += 47721860;  // simulate millis() or micros()
    Serial.print(counter); Serial.print(","); Serial.println(start_time);
    if (counter - start_time >= interval) {  // rollover works just fine
      Serial.println("Trigger Event!");
      start_time=counter;
    }
  }
}
  
void loop() {
}

Note the results:

Code:
4104079960,4056358100
Trigger Event!
4151801820,4104079960
Trigger Event!
4199523680,4151801820
Trigger Event!
4247245540,4199523680
Trigger Event!
104,4247245540
Trigger Event!
47721964,104
Trigger Event!
95443824,47721964
Trigger Event!
143165684,95443824

You're doing a different case than "how to check when millis' unsigned long rolls over" and have changed the case to "how to check when a small data type rolls over" - they are not the same, and the compiler is treating the smaller case differently, hence why it works when you explicitly cast the results.

!c

EDIT: Adding this will be fairly illuminating as to what's happening in your temporary variable handling:

Code:
    Serial.println(counter - start_time);

Results:

Code:
223,248
-25
224,248
-24
225,248
-23
226,248
-22
227,248
-21
228,248
-20
28  Using Arduino / Programming Questions / Re: How to know when serial has finished sending on: August 19, 2012, 03:46:34 pm
Matt, your RS485 transceiver should detail the time it takes to clock out a bit in the datasheet.  For very fast communication, you would need to know this (it's easy to wait too long).  For doing the same thing, I have (generally):

Code:
#include <util/delay.h>

...

#define SER_BPS 57600.0

// serial clear time in uS (how long it takes to punch one bit
// out through the RS485 transceiver at the current bitrate).
// the transceiver adds 0.07uS delay in punching out a bit

#define SER_CLEAR_TM 1000000.0 / SER_BPS + 0.07

...

void write(uint8_t p_dat) {
    
    // TODO: Abstract for non Atmega328P platforms
    
    while (!(UCSR0A & _BV(UDRE0)));
    
// set xmit pin high
    PORTD |= _BV(PORTD5);  
    // clear tx complete flag before write, just incase serial object doesn't
    UCSR0A |= _BV(TXC0);
    
    UDR0 = p_dat;
    

    while(!(UCSR0A & _BV(TXC0)) );
    
    _delay_us(SER_CLEAR_TM);
    
    PORTD &= ~_BV(PORTD5);
    
    
}
29  Using Arduino / Programming Questions / Re: Simple math doing my head in - when is an int treated like an int? on: August 19, 2012, 03:39:13 pm
Is this behaviour (intermediate calcs being influenced by data type of variable) just Arduino, or is it C?  Damn sure this has never happened to me in years of Java..?

C/C++ have that issue everywhere... Just try this anywhere =)

Code:
int foo = 20;
int bar = 35;
float baz = 0.0;

baz = foo / bar;
30  Using Arduino / Programming Questions / Re: Convert byte array to uint32_t on: August 19, 2012, 03:36:03 pm
Use the 'left shift' operator:

Code:
byte[4] x = {...};
uint32_t foo;

...

foo = (uint32_t) x[0] << 24;
foo |=  (uint32_t) x[1] << 16;
foo |= (uint32_t) x[2] << 8;
foo |= (uint32_t) x[3];

There are other ways to skin the cat, you can use addition instead of the 'or' operator, etc.
Pages: 1 [2] 3 4 ... 22