Multitasking on a nano

Hi all, Im after some friendly advice.

i have been playing around with a project for about a week now and im wondering if im going down the wrong path.

I am using a nano with a hx711 + load cell + 16 x 2 i2c lcd it also has 2 LED's (green,red) and the goal is to turn the led to a flashing green for 5 seconds once required load is reached and when it is reached the led shoud turn solid green, but also if the pressure falls below said weight in the 5 seconds i want the board to halt or at least reset. and maybe even a count down on the lcd of 5-0 secs

reading up i went down a couple of routes once i found that delays will take over anything else. I thought millis is what i will need but so far i havent got very far with it as it seemed to interupt certain things still. (maybe i used it wrong,my coding skills are amatuer). Also looking at a few posts ive seen it is in my understanding that millis counts from the time the program starts not from a "trigger".

Before i carry on with this project am i asking too much of the nano with this?

Any advice on how to code this would be greatly appricated i have looked over alot of the posts on here but im kinda stuck in the direction to take.

ive got the code i have so far below without the millis in as i got a bit annoyed and deleted it lol (its probably not very clean but it might help) .

#include <Wire.h> 
#include <LiquidCrystal_I2C.h>
LiquidCrystal_I2C lcd(0x3F,16,2); // set the LCD address to 0x3F for a 16 chars and 2 line display
#include "HX711.h"

#define DOUT 5
#define CLK  6
int LED1  = 2;
int LED2  = 3;


HX711 scale(DOUT, CLK);

float calibration_factor = 357500; //-7050 worked for my 440lb max scale setup
float units;
float ounces;
void setup() {
   
  pinMode(LED1, OUTPUT);
  pinMode(LED2, OUTPUT);

  lcd.backlight(); //open the backlight
  lcd.init(); //initialize the lcd
  lcd.setCursor(0, 0);
  lcd.print("CALIBRATING.....");
  delay(1500);
  lcd.clear();
  delay(500);
  lcd.print("-----READY-----");
  delay(1000);
  lcd.clear();
  
  scale.set_scale();
  scale.tare();  //Reset the scale to 0


long zero_factor = scale.read_average(); //Get a baseline reading  

}

void loop() {

 
  scale.set_scale(calibration_factor); //Adjust to this calibration factor

  Serial.print("Reading: ");
  units = scale.get_units(), 10;
  if (units < 0) {
    units = 0.00;
   
  }
  ounces = units * 0.035274;
  
    lcd.setCursor(0, 1);
  lcd.print("K/G's: ");
  lcd.print(units);
  units = scale.get_units(), 10;
  if (units < 0) 
    units = 0.00;
    if (units <=13)digitalWrite(LED1, HIGH);
        if (units >13)digitalWrite(LED1, LOW);
        if (units >=13)digitalWrite(LED2, HIGH);
        if (units <13)digitalWrite(LED2, LOW);

    


  
}

Thanks in advance. (sorry if this is a noob question and ive missed something)

am i asking too much of the nano with this?

No. What you describe is well within the capabilities of a Nano

Have you looked at Using millis() for timing. A beginners guide, Several things at the same time and looked at the BlinkWithoutDelay example in the IDE ?

I guess that you need a state machine, not multitasking.

DrDiettrich:
I guess that you need a state machine, not multitasking.

Both would be my guess.

@stivit, take some time and write down in as much detail as possible (and in English rather than code) the exact sequence of steps that you want to happen and the conditions when things change. Write each step on a separate line.

If you do that carefully and methodically it will be relatively easy to turn it into working code.

...R
Planning and Implementing a Program

Delay in setup as you have it is not a problem to multitasking and you don't use timing anywhere else.

Arduinos millis() returns an unsigned long giving milliseconds since the board started up.

unsigned long startMs, elapsedMs;
.............. somewhere in the code
    startMs = millis()
.............. later on
    elapsedMs = millis() - startMs;

Time difference is always end time minus start time. This works past rollover, if someone tells you that you need extra code for rollover, they don't know how to do it right and want you to be confused as well. Unsigned math makes this work every time.

In the Arduino IDE Tools menu is Autoformat. It's very useful.

Thank you all for the reply's,
i'm still a bit in over my head i think. i have read through the examples etc and so far have the it booting as i want and once the load cell gets above pressure the green led blinks but i am at a loss on how to time this for 5 seconds and then turn it to a solid green. and then also im not sure how i would make the red led turn on or flash if the pressure was to drop below the value in the 5 seconds needed.

again sorry if these are all noob questions

i would much appreciate if someone could look through and maybe edit the code to show me how to do this.I know its cheeky to ask this but i've been at this a while and don't seem to be getting very far and i believe i would understand it alot more if the code was sat there in front of me.

so far i have this.

#include <Wire.h> 
#include <LiquidCrystal_I2C.h>
LiquidCrystal_I2C lcd(0x3F,16,2); // set the LCD address to 0x3F for a 16 chars and 2 line display
#include "HX711.h"
unsigned long startMillis; 
unsigned long currentMillis;
const unsigned long period = 500;
const byte ledPin = 3;    
#define DOUT 5
#define CLK  6
int LED1  = 2;
int LED2  = 3;


HX711 scale(DOUT, CLK);

float calibration_factor = 357500; //-7050 worked for my 440lb max scale setup
float units;
float ounces;
void setup() {
     Serial.begin(115200);  //start Serial in case we need to print debugging info
  pinMode(ledPin, OUTPUT);
  startMillis = millis();  //initial start time

  pinMode(LED1, OUTPUT);
  pinMode(LED2, OUTPUT);

  lcd.backlight(); //open the backlight
  lcd.init(); //initialize the lcd
  lcd.setCursor(0, 0);
  lcd.print("CALIBRATING.....");
  delay(1500);
  lcd.clear();
  delay(500);
    lcd.print("-----READY-----");
  delay(1000);
  lcd.clear();
  

  scale.set_scale();
  scale.tare();  //Reset the scale to 0


long zero_factor = scale.read_average(); //Get a baseline reading  

}

void loop() {
 
 
  scale.set_scale(calibration_factor); //Adjust to this calibration factor

  Serial.print("Reading: ");
  units = scale.get_units(), 10;
  if (units < 0) {
    units = 0.00;
   
  }
  ounces = units * 0.035274;
  
    lcd.setCursor(0, 1);
  lcd.print("K/G's: ");
  lcd.print(units);
  units = scale.get_units(), 10;
  if (units < 0) 
    units = 0.00;
    if (units <=13)digitalWrite(LED1, HIGH);

        if (units >13)digitalWrite(LED1, LOW);
        if (units >=13)digitalWrite(LED2, HIGH);
           currentMillis = millis();  //get the current "time" (actually the number of milliseconds since the program started)
  if (currentMillis - startMillis >= period)  //test whether the period has elapsed
  {
    digitalWrite(ledPin, !digitalRead(ledPin));  //if so, change the state of the LED.  Uses a neat trick to change the state
    startMillis = currentMillis;  //IMPORTANT to save the start time of the current LED state.
        if (units <13)digitalWrite(LED2, LOW);
  }

 
}

In your state machine, when the load cell signals high pressure you switch to "green blink" state. In that state the green LED blinks. This state is left after 5 seconds, for the "green stable" state. And so on...

  units = scale.get_units(), 10;

There is no way that line is right. It will do something but I am sure it's not what you think or I will guess.
Here below is HX711.h on that function, you should put a float in the ( ) to use set_scale().

// returns get_value() divided by SCALE, that is the raw value divided by a value obtained via calibration
// times = how many readings to do
float get_units(byte times = 1);

Just guessing what you wanted there, float constants should have a decimal point in them so the intent is easy to see.

 units = scale.get_units(10.0);

That sketch takes longer to read carefully because the formatting makes it harder to follow.
Please use the Autoformat tool in your IDE and put a blank line between functions and just to separate code by what it does like printing from weighing, that sort of thing.

I think that if you format then fix those HX711 calls, it will be a lot closer to working. But save yourself time and eyestrain, use the autoformat! It might even get you more helpers.

At some point I would break the sketch into separate input-process-output tasks but you may not be ready for that.

DrDiettrich:
In your state machine, when the load cell signals high pressure you switch to "green blink" state. In that state the green LED blinks. This state is left after 5 seconds, for the "green stable" state. And so on...

What state machine?

The state machine (to be) designed for this project.

LOL, post tha code! LMAO!

To avoid any confusion "state machine" is just a fancy name for one or more variables that keep track of where the program is in a complex set of processes.

The sequence of steps that I mentioned in Reply #3 might be a series of states, or maybe two or three steps might together represent the actions while in one state.

...R

is just a fancy name for one or more variables that keep track of where the program is in a complex set of processes.

IJAFNFOOMVTKTOWTPIIACSOP :o

NALOPKT !

A state machine has a single state variable, that changes when specified events happen. Actions can execute once, on a state transition, or while some state is active.

larryd:
IJAFNFOOMVTKTOWTPIIACSOP :o

That's good stuff you are smokin - care to share it around?

...R

An acronym for your new replacement for 'state machine'. :confused:

IJAFNFOOMVTKTOWTPIIACSOP
is just a fancy name for one or more variables that keep track of where the program is in a complex set of processes.

.

or a simple set of processes, like a 2 state system.

I got lost at about here-

"turn the led to a flashing green for 5 seconds once required load is reached and when it is reached the led shoud turn solid green"

larryd:
An acronym for your new replacement for 'state machine'. :confused:

I had worked that out.

I just don't see how it helps the OP.

...R