2

I've created a function whereby an int ('cleanCount') automatically goes up or down (0-1000) based on the situation. The value changes every few milliseconds.

Based on the value, I would like to turn on or off LEDs. Let's say for every increment of '100' another LED goes on. So if the value is 359 there are 3 leds on, if It would been 899 there would've been 8 LEDs on.

I could simply write

if (cleanCount <= 100) { // turn on NO LEDs
    digitalWrite(led1, LOW);
    digitalWrite(led2, LOW);
    ...
}

...

else if (cleanCount <= 500) { // turn on 4 LEDs
    ...
    digitalwrite(led3, HIGH);
    digitalwrite(led4, HIGH);
    digitalwrite(led5, LOW);
    digitalwrite(led6, LOW);
    ...
}

but that would be a big pile of code which could be way more efficient. Perhaps.. my code isn't even correct.

So how could this be more efficient or perhaps actually working?


The whole code, here below.

int cleanCount = 1000;
int softpotPin = A0; //analog pin 0



void setup () {
    Serial.begin(9600);
    digitalWrite(softpotPin, HIGH); //enable pullup resistor    
}


void loop() {
    int softpotReading = analogRead(softpotPin);
    if (softpotReading < 980) { // IF AANGERAAKT
        digitalWrite(werktIeLED, HIGH); 
        ++cleanCount;
        Serial.println(cleanCount);
        delay(16); // 5x zo snel als leeglopen
    }
    else if (softpotReading > 980) { // IF NIET AANGERAAKT
        digitalWrite(werktIeLED, LOW); 
        --cleanCount;
        Serial.println(cleanCount);
        delay(64); // 1000 / 60 seconden
    }
    else {      // Als er een fout optreed..
        Serial.println("Fout!");
        digitalWrite(werktIeLED, HIGH);    
        delay(250);               
        digitalWrite(werktIeLED, LOW);    
        delay(250);               
    }


}
3
  • If you want the a bar graph effect, the arduino ide has a ino under examples>Display>barGraph maps analog values to ten LEDs
    – RSM
    Commented Apr 7, 2015 at 19:03
  • @RSM but how would I combine that example with my scope: 1 LED per 100 of my variable. That- and multiple LED's should be lid. Commented Apr 7, 2015 at 19:08
  • The code uses the map() function and will lite an LED per 100, it also keeps LEDs on below the current lit
    – RSM
    Commented Apr 7, 2015 at 19:17

3 Answers 3

2

Here is a suggestion with the led pins in an array that you loop over.

I suggest making the array global, so put it outside any functions (usually at the top):

byte led_pins[] = {pin1, pin2, pin3, pin4, pin5, pin6, pin7, pin8};

Then put this in your loop (assumes that you have a int called cleanCount that is in scope:

const int increment = 100;

for (int i = 0; i < sizeof(led_pins) / sizeof(led_pins[0]); i++) {
  boolean onOrOff = cleanCount > (i+1) * increment;
  digitalWrite(led_pins[i], onOrOff);
}
3
  • I'm pretty new to Arduino and coding for it. But uh, do I paste all of that in 'void loop' or a part above 'void setup' and a part in 'void loop' or..? Seems great and character-optimised formatted. Commented Apr 7, 2015 at 15:32
  • I updated the answer
    – user2973
    Commented Apr 7, 2015 at 15:45
  • cleanCount is stated at the top, above the setup, but has the value changing functionality in the loop. I'll post the whole code in a sec. Commented Apr 7, 2015 at 15:57
2

You can use the barGraph example from the Arduino code examples. This gives a bar-type graph and not point. I will give rough explination why it will work and the need not to re-invent the wheel.

    int sensorReading = analogRead(analogPin);
  // map the result to a range from 0 to the number of LEDs:
  int ledLevel = map(sensorReading, 0, 1023, 0, ledCount);

  // loop over the LED array:
  for (int thisLed = 0; thisLed < ledCount; thisLed++) {
    // if the array element's index is less than ledLevel,
    // turn the pin for this element on:
    if (thisLed < ledLevel) {
      digitalWrite(ledPins[thisLed], HIGH);
    } 
    // turn off all pins higher than the ledLevel:
    else {
      digitalWrite(ledPins[thisLed], LOW); 
    }
  }

int ledLevel = map(sensorReading, 0, 1023, 0, ledCount);

This will give you the point in the array, 0-10, for 0-1000, if you replace 1023 with 1000

Simplified map() function:

int point = sensorReading*10/1000 this gives you a range of 0-10, the int keeps it from having decimal points.

As you can see from the for loop it turns on all the LEDs that are in the array to the end and then turns off those not needed.

0

Instead of repeating several calls to digitalwrite you should consider changing the pins directly as described here.

This now depends on which port your LEDs are connected to. Assuming port D you would use DDRD to define the pins as output (usually in setup()) and PORTD to set their values (in loop), e.g.

DDRD = B11111110; // define pins 1..7 as outputs, pin 0 as input

and

PORTD = B11110000; // switch on first 4 LEDs

Now all you need to do is to write a function to map your number range to suitable bit strings.

The function could look like this:

int convert(int n) {                                                                     

  int res = 0;   // start with all pins off (zero)
  while (n > 100) { 
    res <<= 1;   // shift pattern 1 bit (i.e. pin) to the left
    res |= 1;    // "switch on" lowest pin 
    n -= 100;    // defines step size (1 LED for every  100)
  }
  return res;

}

It takes your value and returns an int that you can assign to the port. I.e. for 0..100 it returns 0, for 101..200 it returns 1, for 201..300 it returns 3 = B11, for 301..400 it returns 7 = B111 and so on. (Note that it does not do any sanity checks on the input / output but that's certainly easy for you to add if needed.)

(In response to comment: Note that the bit pattern I use as example for DDRD above is an example: It sets bit / pin 0 as input. If you use convert you would, of course, set the lowest bit of DDRD to 1 to make it an output.)

8
  • 502 error on the link.. But I can use 'port manipulation arduino' as a search term. Looking at the information. Seems great! Commented Apr 7, 2015 at 15:27
  • Link works for me? I'll add a function also. Commented Apr 7, 2015 at 15:32
  • 2
    Problem is that there is always one led lid, even in n<100. Secondly, the DDRD example, has pin D0 as an input, while convert will just write to bit 0. Thirdly, the PORTD example actually lights up the last four leds. Direct port manipulation is not very beginner friendly, and isn't really necessary, unless performance becomes an issue.
    – Gerben
    Commented Apr 7, 2015 at 16:14
  • 1
    Firstly, I am not hired to write code to specs but trying to give hints on how to solve a problem. Adjusting the code so that it lights no led if n < 100 is something I think Sander is well capable of. Secondly, I chose this bit pattern for DDRD to make clear what it means if a bit is 0. But I will add a comment to make sure that this is not missed. Thirdly, that depends on how you define first and last, right? Commented Apr 7, 2015 at 16:26
  • 1
    @Gerben It is not a problem if the first LED is always lid. Actually, that's great because the first one is red, which suggests 'BAD'. No leds visualize less than a red lid one. Perhaps you can add that, Fuenfundachtzig. Besides that; every suggestion is appreciated. Perhaps port manipulation is nog beginner friendly, perhaps. But I'm asking for efficient code, instead of writing every LED in an IF statement, which would be awefully bad. That might result in more mediate code, instead of beginner one. Still: Thanks! Commented Apr 7, 2015 at 16:53

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.