Show Posts
Pages: [1] 2 3 ... 8
1  Forum 2005-2010 (read only) / Syntax & Programs / Re: Program causing Arduino to reset? on: June 12, 2009, 03:03:30 pm
Problem resolved, although I don't understand why.

I moved the parent pointer assignment further down in the constructor for the SensorScreen class, and now it works  :confused

Basically changed this:

Code:
   SensorScreen(char desc[], MenuItem *par ) {
      parent = par;
      strcpy(descript, desc);
      currentDatum=0;
      lastPoll=0;
      refresh=true;
    }
to this:
Code:
   SensorScreen(char desc[], MenuItem *par ) {
      strcpy(descript, desc);
      currentDatum=0;
      lastPoll=0;
      refresh=true;
      parent = par;
    }
2  Forum 2005-2010 (read only) / Syntax & Programs / Re: Program causing Arduino to reset? on: June 12, 2009, 01:29:51 pm
I added another derived class ModeScreen similar to DataScreen, and ModeScreen.maintain() does exactly what I want it to!  DataScreen.maintain() still fails.  I changed the way the value gets returned (changed "return parent;" to "return parent->display(); to ensure the new screen is displayed properly) as well.

Code:
/*******************************************************************************************************
/  CLASS MenuItem
/  base class for all of the various menu screens so that the currentItem pointer may point to any
/  of the sketch's menus.
/
/******************************************************************************************************/

class MenuItem {
  public:
    char descript[16];
    MenuItem* parent;
    virtual MenuItem* display(){};
    virtual MenuItem* maintain(){}; //do any required maintenance, ie-poll sensors to update screen data
};

/*******************************************************************************************************
/  CLASS DataScreen
/  for displaying sensor data
/
/******************************************************************************************************/

class SensorScreen : public MenuItem {
  protected:
    unsigned int currentDatum; //current datum that should be displayed
    unsigned long lastPoll; //time of last sensor data update
    boolean refresh; // flag indicates if screen needs to be refreshed
  
  public:
    SensorScreen(char desc[], MenuItem *par ) {
      parent = par;
      strcpy(descript, desc);
      currentDatum=0;
      lastPoll=0;
      refresh=true;
    }
    MenuItem * display() {
       Serial.println("display");
      lcd.clear();
      lcd.home();
      lcd.print(valueNames[currentDatum]);
      lcd.setCursor(0,1);
      lcd.print(currentDatum);
      lcd.print(":");
      lcd.print(sensorData[currentDatum]);
      return this;
    }
    MenuItem* maintain() {
       //Serial.println("maintain");
      if( millis() - lastPoll > pollInterval ) {
        //poll sensors again;
      }
      if( up.changed && up.pressed ) {
        currentDatum = ( currentDatum < 66 ? currentDatum + 1 : 0 );
        refresh=true;
      }
      if( dn.changed && dn.pressed ) {
        currentDatum = ( currentDatum > 0 ? currentDatum - 1 : 66 );
        refresh=true;
      }

      if( back.changed && back.pressed ) {
        digitalWrite(12, HIGH); //troubleshooting LED
        return parent->display(); //this is where things go bad
      }
      else {
        if(refresh){
          display();
          refresh=false;
        }
        return this;
      }
    }
};

/*******************************************************************************************************
/  CLASS SelectScreen
/  base class for all of the various menu screens so that the currentItem pointer may point to any
/  of the sketch's menus.
/
/******************************************************************************************************/

class SelectScreen : public MenuItem {
  protected:
    int currentSelection;
    boolean refresh;
  public:
    MenuItem *options[2];
    SelectScreen( char desc[] ) {
      strcpy(descript, desc);
      currentSelection=0;
      refresh=true;
      parent = this;
    }
    MenuItem * display() {
      lcd.clear();
      lcd.print(options[currentSelection]->descript);
      return this;
    }
    MenuItem * maintain() {
      if( up.changed && up.pressed ) {
        currentSelection = ( currentSelection < 1 ? currentSelection + 1 : 0 );
        refresh=true;
      }
      if( dn.changed && dn.pressed ) {
        currentSelection = ( currentSelection > 0 ? currentSelection - 1 : 1 );
        refresh=true;
      }
      if( enter.changed && enter.pressed ) {
        return options[currentSelection]->display();
      }
      else {
        if(refresh){
          display();
          refresh=false;
        }
        return this;
      }
    }
};


/*******************************************************************************************************
/  CLASS ModeScreen
/  issue mode to ECU
/
/******************************************************************************************************/

class ModeScreen : public MenuItem {
  protected:
    int currentSelection;
    boolean refresh;
    unsigned int modes;
      
      
  public:
    ModeScreen( char desc[], MenuItem *par ) {
      strcpy(descript, desc);
      currentSelection=0;
      refresh=true;
      parent = par;
      modes=9;

    }
    MenuItem * display() {
      lcd.clear();
      lcd.print(modeDesc[currentSelection][0]);
      lcd.setCursor(0,1);
      lcd.print(modeDesc[currentSelection][1]);
      return this;
    }
    MenuItem * maintain() {
      if( up.changed && up.pressed ) {
        currentSelection = ( currentSelection < 8 ? currentSelection + 1 : 0 );
        refresh=true;
      }
      if( dn.changed && dn.pressed ) {
        currentSelection = ( currentSelection > 0 ? currentSelection - 1 : 8 );
        refresh=true;
      }

      if( back.changed && back.pressed ) {
        return parent->display(); //And this one works fine?!?!
      }
      else {
        if(refresh){
          display();
          refresh=false;
        }
        return this;
      }
    }
};

MenuItem *currentItem;
SelectScreen mainMenu("Main Menu");

SensorScreen sensorScreen("View sensor data", &mainMenu);
ModeScreen modeScreen("Issue Mode", &mainMenu);

void setup() {
  mainMenu.options[0] = &sensorScreen;
  mainMenu.options[1] = &modeScreen;
  Serial.begin(9600);
  lcd.clear();
  lcd.print("hello!");
  currentItem = &mainMenu;
  delay(1000);
  currentItem->display();
  pinMode(12, OUTPUT);
 
}

void loop(){
  up.refresh();
  dn.refresh();
  back.refresh();
  enter.refresh();
  
  currentItem = currentItem->maintain();  
}
3  Forum 2005-2010 (read only) / Syntax & Programs / Program causing Arduino to reset? on: June 12, 2009, 12:42:11 pm
I'm working on a menu system for a project, and for some reason hitting the "back" button which causes a menu screen handler to return a reference to a parent menu causes the Arduino to jump back to the setup function.  I'm not sure if it's doing a full reset because when I added an LED that's turned on right before the return statement, that LED stays on until I actually hit the reset button.  I've pretty much ruled out a hardware issue with the button, so I must be missing something in software.

Any insight is appreciated.

The problem occurs at the indicated line at the end of DataScreen.maintain()

Code:
/*******************************************************************************************************
/  CLASS MenuItem
/  base class for all of the various menu screens so that the currentItem pointer may point to any
/  of the sketch's menus.
/
/******************************************************************************************************/

class MenuItem {
  public:
    char descript[16];
    MenuItem* parent;
    virtual void display(){};
    virtual MenuItem* handleButton( int button ){};
    virtual MenuItem* maintain(){}; //do any required maintenance, ie-poll sensors to update screen data
};

/*******************************************************************************************************
/  CLASS DataScreen
/  for displaying sensor data
/
/******************************************************************************************************/

class SensorScreen : public MenuItem {
  protected:
    unsigned int currentDatum; //current datum that should be displayed
    unsigned long lastPoll; //time of last sensor data update
    boolean refresh; // flag indicates if screen needs to be refreshed
  
  public:
    SensorScreen(char desc[], MenuItem *par ) {
      parent = par;
      strcpy(descript, desc);
      currentDatum=0;
      lastPoll=0;
      refresh=true;
    }
     void display() {
       Serial.println("display");
      lcd.clear();
      lcd.home();
      lcd.print(valueNames[currentDatum]);
      lcd.setCursor(0,1);
      lcd.print(currentDatum);
      lcd.print(":");
      lcd.print(sensorData[currentDatum]);
    }
    MenuItem* maintain() {
       //Serial.println("maintain");
      if( millis() - lastPoll > pollInterval ) {
        //poll sensors again;
      }
      if( up.changed && up.pressed ) {
        currentDatum = ( currentDatum < 66 ? currentDatum + 1 : 0 );
        refresh=true;
      }
      if( dn.changed && dn.pressed ) {
        currentDatum = ( currentDatum > 0 ? currentDatum - 1 : 66 );
        refresh=true;
      }

      if( back.changed && back.pressed ) {
        digitalWrite(12, HIGH); //troubleshooting LED
        return parent; //this is where things go bad
      }
      else {
        if(refresh){
          display();
          refresh=false;
        }
        return this;
      }
    }
};

/*******************************************************************************************************
/  CLASS SelectScreen
/  base class for all of the various menu screens so that the currentItem pointer may point to any
/  of the sketch's menus.
/
/******************************************************************************************************/

class SelectScreen : public MenuItem {
  protected:
    int currentSelection;
    boolean refresh;
  public:
    MenuItem *options[1];
    SelectScreen( char desc[] ) {
      strcpy(descript, desc);
      currentSelection=0;
      refresh=true;
      parent = this;
    }
    void display() {
      lcd.clear();
      lcd.print(options[currentSelection]->descript);
    }
    MenuItem * maintain() {
      if( enter.changed && enter.pressed ) {
        return options[currentSelection];
      }
      else return this;
    }
};


MenuItem *currentItem;
SelectScreen mainMenu("Main Menu");

SensorScreen sensorScreen("View sensor data", &mainMenu);

void setup() {
  mainMenu.options[0] = &sensorScreen ;
  Serial.begin(9600);
  lcd.clear();
  lcd.print("hello!");
  currentItem = &mainMenu;
  delay(1000);
  currentItem->display();
  pinMode(12, OUTPUT);
 
}

void loop(){
  up.refresh();
  dn.refresh();
  back.refresh();
  enter.refresh();
  
  currentItem = currentItem->maintain();  
}
4  Forum 2005-2010 (read only) / Syntax & Programs / Re: Why am I getting this warning? on: May 29, 2009, 11:34:57 pm
Aha, that did it!

I had suspected it was actually in that if() statement but I didn't think to check what millis() would be returning.  Although it makes perfect sense for it to return an unsigned long once you think about it, doesn't it? smiley

Thanks!
5  Forum 2005-2010 (read only) / Syntax & Programs / Why am I getting this warning? on: May 29, 2009, 08:34:39 pm
Hopefully someone can point out what I'm missing here.  I just transitioned a class into its own library (which was a bit of a learning experience for me), and now I'm getting this error


Quote
warning: comparison between signed and unsigned integer expressions

 from this function in the library .cpp.  I've indicated which line the warning is indicated on, and I can't for the life of my understand why that would cause this warning:

Code:
   void DebouncedInput::refresh() {
      status = digitalRead(pin);
      if( status != lastStatus && millis() - lastChangeTime > debounceDelay ) {
        changed=true; /*warning indicated on this line*/
        pressed = inverted ? !status : status;
        released = !pressed;
        lastStatus = status;
        prevChangeTime = lastChangeTime;
        lastChangeTime = millis();
      }
      else {
        changed=false;
        lastReadTime=millis();
      }
    }

Here's the library .h file in its entirety:

Code:
#ifndef SmartInput_h
#define SmartInput_h

class DebouncedInput {
  public:
    DebouncedInput( int inPin, int dbTime);
    DebouncedInput (int inPin, int dbTime, boolean inv );
    
    void refresh();  // Read current status
    long sinceLast(); //time since last status change
    long lastInterval();
    void pullup(boolean pullup);

    int pin;
    boolean status;
    boolean inverted;  //True if a HIGH==released && LOW==pressed at the input, False otherwise.
    long lastReadTime; //time of latest read
    long lastChangeTime;  //time of most recent change
    long prevChangeTime;//time of previous change
    long debounceDelay;
    boolean lastStatus;  //status in last iteration
    boolean pressed;
    boolean released;
    boolean changed;
    
};

#endif

Thanks in advance.
6  Forum 2005-2010 (read only) / Troubleshooting / Re: strange analog input? Wierd... on: October 27, 2009, 07:22:47 pm
In the picture you have the pin connected to 5V via your 100R resistor--in other words, you've added an external pullup resistor--and since the internal resistors are also pullup resistors, of course you're reading 1 all the time.  If you ground the pin you will read 0.
7  Forum 2005-2010 (read only) / Troubleshooting / Re: strange analog input? Wierd... on: October 27, 2009, 02:06:07 pm
The arduino, like any digital device, is only capable of reading a logical '1' or a logical '0' from a digital input.  It has no concept of anything else in that context, so it must choose one or the other.  You may think you have nothing connected to the input, but in reallity lots of things are capacitively or inductively or resistively coupled through e.g. the circuit board substrate or the very air surrounding the chip.  Those things are usually negligible and drowned out by the valid signal when you've got something deliberately connected, but if not then those other things can cause the input to drift towards one or zero depending on what's going on around it.  The same goes for the analog inputs.  If you touch your finger to one of the analog inputs with nothing else attached you will cause the readings to change, for example, since your body has measurable resistive and capacitive proeprties.

Think of it like a weather vane; if you have a strong steady wind you will get meaningful readings.  If it's mostly calm but with gentle intermittent breeze, though, it will just drift around rather randomly.  Connecting a pullup or pulldown resistor or a valid TTL signal will provide that strong steady wind.  
8  Forum 2005-2010 (read only) / Troubleshooting / Re: Atmega328 custom board - Erratic Behaviour on: October 23, 2009, 02:21:50 pm
You're also missing decoupling caps between Gnd and Vcc and AGnd and AVcc on the AVR.  These should be placed in close proximity to the IC's pins.
9  Forum 2005-2010 (read only) / Troubleshooting / Re: urgent, trying to neutralise flourescent tube prob on: October 07, 2009, 08:18:19 pm
You mean when you plug and unplug the main power cables you get big sparks?  If that's the case you shouldn't be making and breaking those connections under load (unless the connectors are specifically designed for it--very few are, and they tend to be big and expensive--not your typical mains plug by any means).  All you're doing is ruining the contacts and potentially creating a fire hazard.  Put a switch of appropriate voltage & current rating in series with your power plugs, and make or break those connections only with the switch off.
10  Forum 2005-2010 (read only) / Troubleshooting / Re: confusing slide potentiometer (how to wire) on: October 07, 2009, 01:39:08 pm
You'll need to meter the pot to identify each pin.  Move the slider to the center, and measure the resistance between pairs of pins until you find the combination that reads the nominal value of the pot (10K in your case).  These are the end points, where you will connect 5V and Ground.  Meter from either one of those pins to the two remaining pins.  At least one of them should read about half of the nominal value (5K) with the slider in the middle of the pot.  This will be the wiper (where you read voltage to determine slider position).  

Now, it's possible that by hooking it up wrong you've damaged the pot, so if you can't get readings as I've described consider the pot toast.
11  Forum 2005-2010 (read only) / Troubleshooting / Re: Homebrew LED Christmas Lights on: October 04, 2009, 11:25:01 am
Remember that SSRs will have a certain leakage current in the off state.  ~10mA is not much to worry about with an incandescent lamp or motor, but is more than enough to visibly light a string of LEDs (albeit dimly).  You can mitigate the problem to some extent by putting several LED strings on each SSR or adding a ballast load in parallel.  
12  Forum 2005-2010 (read only) / Troubleshooting / Re: Homebrew LED Christmas Lights on: October 03, 2009, 04:51:25 pm
I've actually been thinking about doing something like this, but the more control you want over flashing patterns and such, the more wires you need in the string, so it'd've required a prohibitively large harness to get the level of control I had in mind.  If you just want simple chase patterns, you can get away with 3 or 4 interleaved series which requires only 4-9 wires at any point in the harness (depending on how many series/parallel sets you have).

I'll also point out that when you consider the parts and labor involved in building up strings from scratch, it becomes very attractive to buy commercially made strings and hack them up as needed.

For efficiency reasons, you'll want to put LEDs in series as much as possible which means you'll want a higher voltage supply.  See the hardware interfacing forum for that info.
13  Forum 2005-2010 (read only) / Troubleshooting / Re: Too much current on digital pins? on: October 02, 2009, 06:09:55 pm
Are you properly setting the pins up as outputs?  If you use digitalWrite( pin, HIGH) without using pinMode( pin, OUTPUT) first, you will simply be enabling the internal pullup resistor, so you'll be powering an LED through the internal pullup resistor in addition to your external current limiting resistor and only get a very tiny amount of current through the LED.
14  Forum 2005-2010 (read only) / Development / Re: Big LED Ambient System on: November 01, 2009, 08:08:42 pm
Quote
I've read that the Mosfet has a Vgs of +-20V. Can The arduino provide it?

IRF510 MOSFET has a Vgs of 2-4V.  5V from the Arduino will be fine to turn it on.  Other MOSFETS require higher gate-source voltages, but not the IRF510--that's why it's referred to as a "logic level" MOSFET, and why it's ideal for use in Arduino projects etc. where higher voltages are not readily available.
15  Forum 2005-2010 (read only) / Development / Re: Big LED Ambient System on: October 17, 2009, 02:22:30 pm
3.3V is probably a bit low for the green and blue dies in the RGB LEDs.  

But a 4V supply can be more efficient IF you use a native 4V adapter or use a switching DC-DC converter to derive it.  Linear regulators, however, dissipate excess power as heat and won't be any more efficient.  So using an LM317 to step your 5V supply down to 4V before feeding to the LEDs, for example, isn't any more efficient than simply using larger current limiting resistors.  In fact with a large array of LEDs you will quickly exceed the current and power dissipation ratings of the regulator, and you'll be concentrating power dissipation in the regulator as opposed to having it distributed though all of the current limiting resistors.  So if you can find a suitably sized 4V switching power supply, go for that, otherwise just stick with a 5V supply since those are so readily available.  

You actually could wire the RGB LEDs in series pairs with a common anode device at the top and a common cathode device at the bottom and switch each color in the middle, but then you'd need a ~7.5V supply which isn't terribly common, and you'll still need 3 resistors per RGB LED.  Really, discrete R, G, and B LEDs are the way to go if you're concerned about efficiency.
Pages: [1] 2 3 ... 8