Created Sun, 09 Dec 2012 20:13:29 +0000 by SXRguyinMA
Sun, 09 Dec 2012 20:13:29 +0000
I've searched and searched and can't seem to find exactly what I'm looking for. I want to create a basic menu (if you can even call it that) for my LCD display with just a single button to change the menus, and up/down buttons for fan speeds (that'll be controlled only when that fan's menu is displayed). Here's how I want it to go:
Welcome screen (on power-up) | | Display 1 (coolant temp/flow rate) | | Display 2 (Intake fan speed/voltage) | | Display 3 (Exhaust fan 1 speed/voltage) | | Display 5 (Exhaust fan 2 speed/voltage) | | Back to display 1 and so on
There will also be a button-controlled servo to open and close a door but that will be independent of the menu system and not displayed.
Obviously I need 5 interrupts (flow meter, fan 1, fan 2, fan 3, servo button) which is why I'm going to use a ChipKIT MAX32 which has 5 interrupts and plenty of I/O for controlling fan speeds, etc. so that problem it solved.
I've got each system (except fan speed control) working independently with separate coding and each works fine (temp/flow works fine, fan speed display works fine). I just can't figure out how to merge them all together into a single working unit. I've seen several different menu libraries but they seem way more complex than what I need. I was thinking button state change or something but can't figure out how to get it all working properly.
What's the best way to go about this?
Mon, 10 Dec 2012 20:34:35 +0000
The first thing you need to get your head around is the concept called the "Finite State Machine". This is the best way to manage multiple tasks at once on a microcontroller.
I have written a tutorial for it here: [url]http://hacking.majenko.co.uk/finite-state-machine[/url]
Basically, each device (including the LCD menu) has an associated "state". Different external events change that state, be it a button press, a sensor triggering, or whatever.
For the LCD, the different states will be the different pages of the menu, and when in different states, the other buttons will do different things, like changing the fan speed, for example.
Fri, 14 Dec 2012 01:50:01 +0000
Cool that definitely seems the best way to do it. Thanks!
On a different note, I'm working on transferring the code (one part at a time) to the Max32 from my Arduino. The first bit I tried is fan RPM and LCD display. All I get on the LCD is gibberish with the Max, however on the Arduino it's perfectly fine. I also had to remove the "sei();" and "cli();" for it to compile. Here's what I'm trying to get working:
//Code for HAF XB mod by Will Lyon
/*To disable interrupts:
cli(); // disable global interrupts
and to enable them:
sei(); // enable interrupts
*/
#include <LiquidCrystal.h>
LiquidCrystal lcd(9, 8, 7, 6, 5, 4);
volatile int NbTopsFan;
int Calc;
int fan1 = 2;
typedef struct{
char fantype;
unsigned int fandiv;
}fanspec;
fanspec fanspace[3]={{0,1},{1,2},{2,8}};
char fan = 1;
void rpm ()
{
NbTopsFan++;
}
void setup()
{
lcd.begin(16, 2);
lcd.setCursor(0, 0);
pinMode(fan1, INPUT);
attachInterrupt(0, rpm, RISING);
lcd.print(" Fan 1 Speed ");
}
void loop (){
NbTopsFan = 0;
sei();
delay (1000);
cli();
Calc = ((NbTopsFan * 60)/fanspace[fan].fandiv);
lcd.setCursor(4, 1);
lcd.print (Calc, DEC);
lcd.setCursor(8, 1);
lcd.print (" RPM");
}
Thoughts? :?:
Fri, 14 Dec 2012 10:03:09 +0000
I have not used a lcd library but you could try delays between lcd.prints
Fri, 14 Dec 2012 10:17:29 +0000
I have only ever used the LCD library in 8 bit mode, and not 4 bit mode. I have had it working perfectly fine like that.
Out of interest, why are you messing with disabling and enabling interrupts? delay() (and anything that uses millis()) requires interrupts to be running. You should only have to worry about interrupts at all when you have absolute (cycle precise) timing critical applications, or interrupt sensitive operations (data communications etc). An LCD isn't anywhere near as critical, being a synchronous transfer of data (clock driven).
Also, once you have your FSM, delay() will become redundant (except for very very very short delays between data pulses, for instance) as it breaks the FSM model.
Mon, 17 Dec 2012 17:43:54 +0000
Ok here's what I've got working right now:
//Code for HAF XB mod by Will Lyon
#include <LiquidCrystal.h>
LiquidCrystal lcd(9, 8, 7, 6, 5, 4);
volatile int NbTopsFan;
int Calc;
int fan1 = 2;
typedef struct{
char fantype;
unsigned int fandiv;
}fanspec;
fanspec fanspace[3]={{0,1},{1,2},{2,8}};
char fan = 1;
void rpm ()
{
NbTopsFan++;
}
void setup()
{
lcd.begin(16, 2);
lcd.setCursor(0, 0);
pinMode(fan1, INPUT);
attachInterrupt(0, rpm, RISING);
lcd.print(" Fan 1 Speed ");
}
void loop (){
NbTopsFan = 0;
delay (1000);
Calc = ((NbTopsFan * 60)/fanspace[fan].fandiv);
lcd.setCursor(4, 1);
lcd.print (Calc, DEC);
lcd.setCursor(8, 1);
lcd.print (" RPM");
}
Now I've assigned the fan's input to pin 2, however it only works when the input is connected to pin 3, not pin 2 :shock:
Also, at 12v the fan shows 2250rpm. If I reduce the fan to 5v it shows "9000" rpm instead of "900." How do I get it to drop the last zero?
Mon, 17 Dec 2012 18:24:31 +0000
I've updated it to show the fan speed and voltage, now I want to implement this into the FSM and add 3 more identical screens, 2 for other fans and 1 for the water pump. I'm also having the same "extra 0" problem with the voltage as with the rpm. 11V/~2100rpm, 4.8V/~840rpm but shows "8400RPM/4.821V", the problem being the extra "0" on the RPM and extra "1" on the voltage. Here's my current code:
//Code for HAF XB mod by Will Lyon
#include <LiquidCrystal.h>
LiquidCrystal lcd(9, 8, 7, 6, 5, 4);
volatile int NbTopsFan;
int Calc;
int fan1 = 2;
typedef struct{
char fantype;
unsigned int fandiv;
}fanspec;
fanspec fanspace[3]={{0,1},{1,2},{2,8}};
char fan = 1;
void rpm ()
{
NbTopsFan++;
}
void setup()
{
lcd.begin(16, 2);
lcd.setCursor(0, 0);
pinMode(fan1, INPUT);
attachInterrupt(0, rpm, RISING);
lcd.print(" Fan 1 Status ");
}
void loop (){
NbTopsFan = 0;
delay (1000);
Calc = ((NbTopsFan * 60)/fanspace[fan].fandiv);
lcd.setCursor(0, 1);
lcd.print (Calc, DEC);
lcd.setCursor(4, 1);
lcd.print ("RPM");
lcd.setCursor(9, 1);
float f = analogRead(0) * 12.05 / 1023; // 12.0=> 25
lcd.print(f, 2);
lcd.setCursor(14, 1);
lcd.print("V");
}
Mon, 17 Dec 2012 19:03:32 +0000
New problem: I'm finding that after 5 mins or so the ChipKIT Max32 seems to freeze. Th display is still there but it will no longer update until I reset the board. Thoughts?