Help with how to approach my aquarium controller

Hello Guys. Firstly sorry for posting and having to ask, but I feel that unless I try here, I will not be able to achieve my project. I feel helpless at the moment, I just spent a while in the arduino chat room on freenode and didn't find it welcoming, I was called ignorant within a minute of entering due to my lack of understanding the phi_prompt libraries, I merely stated I am having problems compiling some of the example codes.

I hope someone on here is able to help me start on the right track to achiving my goal.

I have built a rudimentary aquarium controller which doses 3 peristaltic pumps, turns on some lights and co2, feeds fish by triggering an autofeeder which has it turned out had a PIC inside, and displays various events that occur when the timers are activated such as "dosing macro" or "feeding fish", then it returns to a main display.

I am building a new one for a reef aquarium I have built which is still a work in progress. and I want to disregard anything I did previously as it was a very crude way of doing things.

There are a few things I wish to achive with my controller, and I hope with the help of this forum and the community I can achive that, and expand my knowledge of the arduino platform.

Simply, at the minimum, I would like to use my sainsmart 2x16 5 button LCD shield, and an UNO, to control the duration to which a small 6-12v peristaltic pump runs for, the pump will simply be connected to a voltage source, and a relay which is controlled by one output pin on the arduino per relay.

Ideally I just want to change a value in the code which when that 'chunk' of code is executed the value set will be used.

I will explain a little more because I am pants at explaining what I conceptualise..

I am completely stuck as to how I can raise a menu on the screen, that will allow me to input how long the pump runs for.

I understand I know little, but I am willing to learn, I do not expect people to faux-code everything for me leaving me to fill in the blanks..

I have an arduino uno and a DFrobot LCD 2x16 + 5 button shield, from what I can tell, the sainsmart 2x16lcd is exactly the same.

I would like to use this, but I believe the button input might pose a problem, it uses one input with 5 SPST momentarys with differing resistor values.

Here is the flow of what I wish to do as a minimum.

  1. By pressing a button, the arduino displays onto the LCD, a menu offering Pump 1, Pump 2, Pump 3.

  2. Either pump is selected by pressing up or down, then select, once selected, I can press up or down to change the pumps value, of which will be ML (millilitre).

  3. Once for example Pump 2 is selected, the screen will display
    "Pump 2 amount"
    "0.0ml"

  4. Pressing up will increment by 0.1ml and pressing down will simply return to the highest value of 3.0ml or some other chosen upper limit.

  5. Pressing select will save the setting. This is something I have no idea how to do, and where I feel hopelessly inadiquate with programming an arduino..

  6. Some how, a function/ block of code will run once daily (perhaps with timealarm library, which I have used) for example

  digitalWrite(3, LOW);
  delay(1100);
  digitalWrite(3, HIGH);

Where the time 1100ms is to be determined by the selection in the menu, ml is to be converted to an ms value some how, which will allow easy of calibration, which will be done in the sketch, and prior to uploading.

This is how I have run pumps before, they will run for 1100ms, which I have timed to be around 1ml of solution, this varies with density etc, but does not need to be specific.

The reason I would like to have it 'point' to a chunk of code, is because I may change the motor in future, and would like to change the code to perform a certain amount of steps on a stepper motor with various arduino stepper drivers, such code I feel would readily be pastable from examples into the chunk.

I simply need to build the menu, and have the selections change a value in the sketch somewhere.

I would ultimately like the menu to change an int value.

Can anybody help me start my project, perhaps even explain where my understanding is going wrong, where I am able to achieve or not...

I am looking forward to becoming part of the community. I will just write out a simple sketch that will at least get the basics running and post it here.

Thanks in advance guys and gals!
Jay

Ok what you want is totally doable. To prompt a menu with a button I would use ext int0 or int1.

Then there are many ways do handle arrows selections with buttons and so on. Ill speak for what Ive done. If you can use millis() and understand it, you can do all what you suggested.
I work with "states" and draw them on a board. You can move from one state to anoher by doing choises. Your first state is select pump. Next state is ml selection and so on. I handle different states by certain triggers and if elses. And use millis() to get lecture from buttons and debouncing. With millis() you can also handleother stuff while doing menu selection.

TLDR: millis() is one way to do it.

Hello Mart256, thank you for your response.

I am quite baffled by what you have written, so I shall start elementary, with what I think I need to do in order to perform the first part of your response.

I think hardware wise, I should just set up some external interup switches first?

jaylc005:
Hello Mart256, thank you for your response.

I am quite baffled by what you have written, so I shall start elementary, with what I think I need to do in order to perform the first part of your response.

I think hardware wise, I should just set up some external interup switches first?

I was thinking one button to ext int, and the others to digital pins which are going to be read by digitalwrite inside the state loop.

Hello, Well I have the original buttons which offer up down left right and select (also a reset) and these are all connected to one input via differing resistors, the code to run them worked like this on my last project

  // LCD shield Key Settings
  int lcd_key     = 0;
  int adc_key_in  = 0;

 #define btnPRIMEPHOS 0
 #define btnPRIMEMICRO 1
 #define btnFEED 2
 #define btnPRIMEMACRO 3
 #define btnLightsOn 4
 #define btnNONE 5


  int read_LCD_buttons()
  {
  adc_key_in = analogRead(0); //Read button value from the sensor.
  if (adc_key_in > 1000) return btnNONE;
  if (adc_key_in < 50)   return btnPRIMEPHOS;
  if (adc_key_in < 195)  return btnPRIMEMICRO;
  if (adc_key_in < 380)  return btnFEED;
  if (adc_key_in < 555)  return btnPRIMEMACRO;
  if (adc_key_in < 790)  return btnLightsOn;
  return btnNONE;
  }

Today. I connected up a simple momentary switch from GND to Pin 2 INT0, and played with some example code that turns on and off, the backlight of the screen (as pin13LED was hidden under the shield, it sufficed :)) copied from an example, I am just trying to get my head around what is occuring

/* switch
 * 
 * Each time the input pin goes from LOW to HIGH (e.g. because of a push-button
 * press), the output pin is toggled from LOW to HIGH or HIGH to LOW.  There's
 * a minimum delay between toggles to debounce the circuit (i.e. to ignore
 * noise).  
 *
 * David A. Mellis
 * 21 November 2006
 */

int inPin = 2;         // the number of the input pin
int outPin = 10;       // the number of the output pin

int state = HIGH;      // the current state of the output pin
int reading;           // the current reading from the input pin
int previous = LOW;    // the previous reading from the input pin

// the follow variables are long's because the time, measured in miliseconds,
// will quickly become a bigger number than can be stored in an int.
long time = 0;         // the last time the output pin was toggled
long debounce = 200;   // the debounce time, increase if the output flickers

void setup()
{
  pinMode(inPin, INPUT);
  pinMode(outPin, OUTPUT);
}

void loop()
{
  reading = digitalRead(inPin);

  // if the input just went from LOW and HIGH and we've waited long enough
  // to ignore any noise on the circuit, toggle the output pin and remember
  // the time
  if (reading == HIGH && previous == LOW && millis() - time > debounce) {
    if (state == HIGH)
      state = LOW;
    else
      state = HIGH;

    time = millis();    
  }

  digitalWrite(outPin, state);

  previous = reading;
}

Ok, I wrote some small code using an example, just to test an interrupt

#include <LiquidCrystal.h>

     
/* 
Simple Interrupt example
by: Jordan McConnell
SparkFun Electronics
created on 10/29/11
license: Beerware- feel free to use this code and maintain
attribution. If we ever meet and you are overcome with gratitude,
feel free to express your feelings via beverage.
*/

int ledPin = 13;  // LED is attached to digital pin 13

LiquidCrystal lcd(8, 9, 4, 5, 6, 7); //LCD PINS

void setup() {  
lcd.begin(16, 2);  

  attachInterrupt(0, PumpMenu, FALLING); //pin 0 interrupt

}

void loop() {
lcd.setCursor(0,0);  lcd.print("Reef Idle screen");
lcd.setCursor(0,1);  lcd.print("                ");
delay(5000);
}

// Interrupt service routine for interrupt 0
void PumpMenu() {

    lcd.print("Pump Menu");
    delayMicroseconds(5000);

    
}

So far, it simply displays reef idle screen, and when I press the button, it will print randomly on the screen pump menu, the more I press, the more appear, after some time, depending on when I interrupt the loop, it will jump back to the reef idle screen.

So I can succesfully print from an interrupt, although it soon jumps back to the loop.

I understand and tested delay and obviously it does not work inside an ISR, I also tried delayMicroseconds hoping it would hold pumpmenu on the screen for 5 seconds, but the loop delay seems to be the principle control here…

For some reason, pin13 led flashes even if i remove that portion of the code, that is part of the original example

mart256:
To prompt a menu with a button I would use ext int0 or int1.

Interrupts should only be used when necessary and then only reluctantly and to the least extent possible. There is absolutely nothing about handling button input that requires interrupts, and using interrupts introduces a lot of design issues which will just make it harder to get a working solution.

To display the menu system I suggest you implement a state machine to keep track of which menu is currently displayed. It is easy to read and debounce buttons and detect transitions yourself following the examples that come with the IDE, or you can use the Bounce library to make it even easier. The output either way would be that you know when a button has been pressed and which button it was. You can use that to trigger code within your state machine. Simple state machines like this can be implemented by defining a set of constant values representing the different states, defining a global variable to hold the value representing the current state, and using a switch/case statement to execute the code corresponding to the current state.

Since you want to control multiple things at one you should use a non-blocking approach - Robin2 posted some example code which demonstrates this technique very well: http://forum.arduino.cc/index.php?topic=223286.0

To save the configuration values I suggest you define a struct to hold the current configuration and use the EEPROM write anything code fragment from the playground to write it to EEPROM each time the configuration changes, and read it back from EEPROM at startup.

Hello Peter H. Thank you for your addition.

I have spent the last few hours trying to get my head around interrupts, still none the wiser however :slight_smile:

I keep finding myself in a position where I am baffled by numerous people with numerous abstractions which always leave me feeling like achieving this is outside of the scope of my abilities.

I could achieve most of what I wish to do by simply coding up a sketch and just connecting up a USB each time to change the sketch..

This has worked well for me in the past, I did wish for redundancy from the IDE but if I am honest, I am further baffled by this now and the work seems to be excessive compared to the gain.

I don't want to waste anybodies time, I feel I wont readilly absorb the information enough.

Thanks for taking the time to advise me.

Kind regards.
Jay

jaylc005:
I keep finding myself in a position where I am baffled by numerous people with numerous abstractions which always leave me feeling like achieving this is outside of the scope of my abilities.

That's a normal healthy situation when you are facing a significant learning curve. If you break the problem down into small parts rather than try to learn how to do everything in one go, I'm sure you will find it easier to understand. I suggest you start with Robin2's example and understand the general approach it is demonstrating, and then use that approach to implement a little state machine to manage the user interface. This doesn't need to be the all-singing and all-dancing final version - just a minimal menu system that you can use to figure out how this stuff works. For example you could start with a menu that displays a different screen depending which button was pressed.

My first knee jerk response to your suggestion was me thinking "hmm, I can do that" then I realised, you mean via the statemachine you mention, not my way which will be simple lcd.prints upon a button input, which is my poor way of coding, do somehting, then somehting else, I am sure yo uhave seen it more often than once.

I do not have any servo's, or breadboard, which makes prototyping very tedious, i have to wrap or solder everything at the moment, and just looking at the code, there seems to be much in there I will probably never use, it doesn't really follow one thing at a time, again, there are numerous abstracts in that code that are baffling to me.

I am getting errors trying to upload that example to my arduino, saying INPUT_PULLUP was not declaired

Again. I think I will just leave this idea out.
This after all, is just the most fundamental part I require, but what I actually NEED I feel I can accomplish with my traditional pants way of linear coding if you can even call it that.

I certainly take my hat off to you guys who absorb this sorta stuff like a sponge, but I am feeling very defeated by the suggested approaches to my goal.

Thanks again.
Jay

PeterH:

mart256:
To prompt a menu with a button I would use ext int0 or int1.

Interrupts should only be used when necessary and then only reluctantly and to the least extent possible. There is absolutely nothing about handling button input that requires interrupts, and using interrupts introduces a lot of design issues which will just make it harder to get a working solution.

To display the menu system I suggest you implement a state machine to keep track of which menu is currently displayed. It is easy to read and debounce buttons and detect transitions yourself following the examples that come with the IDE, or you can use the Bounce library to make it even easier. The output either way would be that you know when a button has been pressed and which button it was. You can use that to trigger code within your state machine. Simple state machines like this can be implemented by defining a set of constant values representing the different states, defining a global variable to hold the value representing the current state, and using a switch/case statement to execute the code corresponding to the current state.

Since you want to control multiple things at one you should use a non-blocking approach - Robin2 posted some example code which demonstrates this technique very well: http://forum.arduino.cc/index.php?topic=223286.0

To save the configuration values I suggest you define a struct to hold the current configuration and use the EEPROM write anything code fragment from the playground to write it to EEPROM each time the configuration changes, and read it back from EEPROM at startup.

Yep, the state machine is the name to the stuff I tried to explain.
External interrupt may be not necesary in this case and I didnt want to mess things up, but Ive seen other people putting lcds system to sleep and waking them with ext interrupt. I though you could do that someday and with ext int already implemented would be easier. Anyway it doesnt hurt to learn interesting stuff :wink:

Jay, I hardly recommend to study the example suggested above. That example updates every state each loop. What you might try to do is a backgroundstate and other states which are only accesable by pressing the button. This is how your lcd can work. Backgroumd state handles pumps and stuff, and secondary states are the menu choises.

Well this is where I am getting confused, I am suggested to take one approach at a time, but in the same line being suggested multiple abstracts, libraries, all of which seem to have hardware dependencies which I need to solder up or mess around with which seem to bear no purpose to what I actually want.

I don't think the help I am asking for is available here, the help I am seeking clearly is too elementary for here.

I understand all the boring stuff like digitalWrites, delays, else if etc, I can rough code up most of what I need bar this input menu, but all of these suggestions seem to be overly complex for me.

You guys don't seem to agree now on which approach I should take , as you have both suggested that neither of the others is the best way to go for my intentions.

Thanks for the advice but it has been overwhelming just the suggestions before searching and getting all the results google returns.

Thanks guys but I think I will give it a rest.

Cheers.
Jay

I'm sorry you feel like that, because I think you've already made good progress with the projects you've completed so far and I don't see any reason you couldn't continue and complete the project if you want to. I didn't envisage that the prototyping would involve any different hardware than you already have. You mentioned a UNO and a display/button shield and that is exactly what I'd use for prototyping.

Note that you will need a driver circuit between the Arduino and any motor or relay that it is going to operate. The Arduino I/O pins are safe for 20mA and have an absolute limit of 40mA which is way less than you need to operate even a tiny relay, and they need flyback protection in order to drive any inductive loads. You can get motor shields or separate driver boards which contain the necessary electronics - or you can make up your own circuit from discrete components if you want.

This is where my english betrays me. By hardly recommend I meant totally recommend. I agree with Peters solution at 100% never wanted to say another thing. Sorry for confusions you are in the right way we all went through this.

I tought hardly and totally where sinonym they are actually quite the opposite damn mind. I just suggested some changes but the main idea is the way to go.

Thanks Peter, I understand the output limitations etc, driving stuff on outputs etc, I can do all of that no problem, I dont like making then breaking just to see if something might work. But unfortunately for me, the difference between what I have already made, and what I want to make is this, I looked up videos months, maybe years before getting an arduino such as what is an arduino, how easy it is to program an arduino, etc etc, they all shown me the basics I knew I could compete with and when it came to building my old controller, I did so within a week, and it ran flawlessly.

With the suggestions of what I seemingly need just to press up and down a few times to select a desired output running time, seems overly complex, so complex on the outset to me that I decided to go for a lie down…

I dont know what else there is to suggest or discuss.

I need starter points to learn, anything i have found for starters, is not compatable with my sheild anyway, so i either need to code around that, usually creating issues for compiling because expected declarations for inputs are missing etc, or I have to make buttons up which all use an individual input.

Then I have to mess with debounce and all that stuff.

I really don’t think my last project is a measure of what I can achieve here.

Don’t feel sorry. A community cannot fulfill every members request.

thanks.

OK guys, I have pulled my finger out just a little, I still don’t know what I am doing, but this code

#include <LiquidCrystal.h>

#include <SM.h>

LiquidCrystal lcd(8, 9, 4, 5, 6, 7); 
  

SM Simple(S1);//create simple statemachine

#define Select A0//pin to toggle led on and off
#define Up A1
#define Down A2
#define Left A3
#define Right A4

#define led 13

void setup(){
    lcd.begin(16, 2); 
  pinMode(led, OUTPUT);
}

void loop(){
  EXEC(Simple);//run statemachine
}

State S1(){
  digitalWrite(led, HIGH);//turn led on
   lcd.clear();  lcd.print("LED ON");
  if(digitalRead(Select)) Simple.Set(S2);//wait for toggle pin to go high and change state to S2
}

State S2(){
    
  if(!digitalRead(Select)) Simple.Set(S3);//wait for toggle pin to go low and change state to S3
}

State S3(){
  digitalWrite(led, LOW);//turn led off
  lcd.clear();  lcd.print("LED OFF");
  if(digitalRead(Select)) Simple.Set(S4);//wait for toggle pin to go high and change state to S4
}

State S4(){
  if(!digitalRead(Select)) Simple.Set(S1);//wait for toggle pin to go low and change state to S1
}

has given me the ability to change states, with each press of a button, defined in here as Select, LED on pin 13 turns on and off, also on the LCD it displays LED ON or LED OFF.

Any ideas where I can go with this…
?

I will have to make up a keypad, as I think making these single input push buttons that come with the shield work will be too much hassle.

For now, all of the buttons trigger as an input on A0, so pushing any button, changes the state of the led and display…

I don't know how the buttons work ojn the shield you're using but I suspect they'll just be connected to I/O pins. In that case, reading the button state will be as easy for the shield as in any other case. Look at the state change detection example to see how to debounce an input and detect button presses - you could probably get that working using your lcd/button shield by creating a copy that uses the pin numbers your shield connects the buttons to.

None of what you're trying to do seems especially difficult, and I suspect the reason that you're finding it so intimidating is that you're trying to solve the whole thing in one go. That's not the best way to tackle problems like this. Take it one step at a time, reading and trying the examples that show you how to use the techniques relevant to that step. You need to be able to detect button presses on the shield, you need to display text, and you should plan to implement a simple state machine to manage the menu system you're going to write. Individually, none of these things are especially difficult to do.

I am going through the SMlib at arduino playground in detail, trying the various examples, I have just played around a little with it.

My problem with the shield is, it has 5 buttons, but they all go into A0 and have differing resistors, i cant explain how it works I can only show you the appropriate code

  // LCD shield Key Settings
  int lcd_key     = 0;
  int adc_key_in  = 0;

 #define btnPRIMEPHOS 0
 #define btnPRIMEMICRO 1
 #define btnFEED 2
 #define btnPRIMEMACRO 3
 #define btnLightsOn 4
 #define btnNONE 5


  int read_LCD_buttons()
  {
  adc_key_in = analogRead(0); //Read button value from the sensor.
  if (adc_key_in > 1000) return btnNONE;
  if (adc_key_in < 50)   return btnPRIMEPHOS;
  if (adc_key_in < 195)  return btnPRIMEMICRO;
  if (adc_key_in < 380)  return btnFEED;
  if (adc_key_in < 555)  return btnPRIMEMACRO;
  if (adc_key_in < 790)  return btnLightsOn;
  return btnNONE;
  }

This part is complicated to me, I understand bits of the code have been renamed, but I simply copied this chunk of code from an example.

This is how it determines which button is pressed, do you have any pointers on how I could perhaps do this another way?

Otherwise, I will either build a keypad or I will solder wires from the current buttons strait to inputs 1 2 3 4 and 5.

Thank you peter H you have given me a little more faith in my self.

regards.
Jay

jaylc005:
This is how it determines which button is pressed, do you have any pointers on how I could perhaps do this another way?

It seems that your shield is combining all the buttons with a resister network so the Arduino sees a different voltage on an analog pin depending which buttons are pressed. The code to handle this type of input is similar to reading an ordinary pushbutton on a digital I/O pin, except that it can return multiple values not just high and low. In order to detect button presses you need to keep track of what button is currently pressed, and see when this changes.

// global data
int previousButton = btnNONE;

// code called from loop()
currentButton = read_LCD_buttons();
if(currentButton  != previousButton)
{
    // button press or release has occurred
    if(currentButton != btnNONE)
    {
        // button press has occurred
        handleButtonPress(currentButton);
    }
    previousButton = currentButton;
}

// function you will write to do something when a button press occurs
void handleButtonPress(int button)
{
    your code here
}