Is there a simpler way of doing this...?

I’m sure there must be a simpler way of doing this. It works but it’s inelegant and I would like to condense it as much as is possible. What would be the best way to approach this?

Also, while I say it works… I have noticed that when on the boundaries, the LED coming on or off can flicker as it straddles different logic blocks… Is there a neat way to try to prevent this by only turning the next LED on or off if it’s a little way into the boundary? I guess this would require separating the on and off condition arguments and staggering the boundaries perhaps?

Fan_Speed = constrain(as100.analogReadSmooth(Input_Fan_Speed),395,825);
  Fan_Speed = map(Fan_Speed,395,825,0,900);

  if(Fan_Speed <100){
    pinMode(Output_Fan1, OUTPUT);
    pinMode(Output_Fan2, INPUT);
    pinMode(Output_Fan3, INPUT);
    pinMode(Output_Fan4, INPUT);
    pinMode(Output_Fan5, INPUT);
    pinMode(Output_Fan6, INPUT);
    pinMode(Output_Fan7, INPUT);
    pinMode(Output_Fan8, INPUT);
    pinMode(Output_Fan9, INPUT);
  }
  if(Fan_Speed >=100 && Fan_Speed <200){
    pinMode(Output_Fan1, OUTPUT);
    pinMode(Output_Fan2, OUTPUT);
    pinMode(Output_Fan3, INPUT);
    pinMode(Output_Fan4, INPUT);
    pinMode(Output_Fan5, INPUT);
    pinMode(Output_Fan6, INPUT);
    pinMode(Output_Fan7, INPUT);
    pinMode(Output_Fan8, INPUT);
    pinMode(Output_Fan9, INPUT);
  }
  if(Fan_Speed >=200 && Fan_Speed <300){
    pinMode(Output_Fan1, OUTPUT);
    pinMode(Output_Fan2, OUTPUT);
    pinMode(Output_Fan3, OUTPUT);
    pinMode(Output_Fan4, INPUT);
    pinMode(Output_Fan5, INPUT);
    pinMode(Output_Fan6, INPUT);
    pinMode(Output_Fan7, INPUT);
    pinMode(Output_Fan8, INPUT);
    pinMode(Output_Fan9, INPUT);
  }
  if(Fan_Speed >=300 && Fan_Speed <400){
    pinMode(Output_Fan1, OUTPUT);
    pinMode(Output_Fan2, OUTPUT);
    pinMode(Output_Fan3, OUTPUT);
    pinMode(Output_Fan4, OUTPUT);
    pinMode(Output_Fan5, INPUT);
    pinMode(Output_Fan6, INPUT);
    pinMode(Output_Fan7, INPUT);
    pinMode(Output_Fan8, INPUT);
    pinMode(Output_Fan9, INPUT);
  }  
  if(Fan_Speed >=400 && Fan_Speed <500){
    pinMode(Output_Fan1, OUTPUT);
    pinMode(Output_Fan2, OUTPUT);
    pinMode(Output_Fan3, OUTPUT);
    pinMode(Output_Fan4, OUTPUT);
    pinMode(Output_Fan5, OUTPUT);
    pinMode(Output_Fan6, INPUT);
    pinMode(Output_Fan7, INPUT);
    pinMode(Output_Fan8, INPUT);
    pinMode(Output_Fan9, INPUT);
  }
  if(Fan_Speed >=500 && Fan_Speed <600){
    pinMode(Output_Fan1, OUTPUT);
    pinMode(Output_Fan2, OUTPUT);
    pinMode(Output_Fan3, OUTPUT);
    pinMode(Output_Fan4, OUTPUT);
    pinMode(Output_Fan5, OUTPUT);
    pinMode(Output_Fan6, OUTPUT);
    pinMode(Output_Fan7, INPUT);
    pinMode(Output_Fan8, INPUT);
    pinMode(Output_Fan9, INPUT);
  }
  if(Fan_Speed >=600 && Fan_Speed <700){
    pinMode(Output_Fan1, OUTPUT);
    pinMode(Output_Fan2, OUTPUT);
    pinMode(Output_Fan3, OUTPUT);
    pinMode(Output_Fan4, OUTPUT);
    pinMode(Output_Fan5, OUTPUT);
    pinMode(Output_Fan6, OUTPUT);
    pinMode(Output_Fan7, OUTPUT);
    pinMode(Output_Fan8, INPUT);
    pinMode(Output_Fan9, INPUT);
  }
  if(Fan_Speed >=700 && Fan_Speed <=800){
    pinMode(Output_Fan1, OUTPUT);
    pinMode(Output_Fan2, OUTPUT);
    pinMode(Output_Fan3, OUTPUT);
    pinMode(Output_Fan4, OUTPUT);
    pinMode(Output_Fan5, OUTPUT);
    pinMode(Output_Fan6, OUTPUT);
    pinMode(Output_Fan7, OUTPUT);
    pinMode(Output_Fan8, OUTPUT);
    pinMode(Output_Fan9, INPUT);
  }
  if(Fan_Speed >=800 && Fan_Speed <=900){
    pinMode(Output_Fan1, OUTPUT);
    pinMode(Output_Fan2, OUTPUT);
    pinMode(Output_Fan3, OUTPUT);
    pinMode(Output_Fan4, OUTPUT);
    pinMode(Output_Fan5, OUTPUT);
    pinMode(Output_Fan6, OUTPUT);
    pinMode(Output_Fan7, OUTPUT);
    pinMode(Output_Fan8, OUTPUT);
    pinMode(Output_Fan9, OUTPUT);
  }

Yes and it is quite simple:

pinMode(Output_Fan1, OUTPUT); //Always output
pinMode(Output_Fan2, Fan_Speed >= 100 ? OUTPUT : INPUT);
pinMode(Output_Fan3, Fan_Speed >= 200 ? OUTPUT : INPUT);
//And so on...

may no minimize code, but captures settings in a table

specific pins can be specified in enumeration

enum { Fan1 = 1, Fan2, Fan3, Fan4, Fan5, Fan6, Fan7, Fan8, Fan9 };

typedef struct {
    byte    pin;
    int     spd;
} Fan_t;

Fan_t fans [] = {
    { Fan1,    0 },
    { Fan2,  100 },
    { Fan3,  200 },
    { Fan4,  300 },
    { Fan5,  400 },

    { Fan6,  500 },
    { Fan7,  600 },
    { Fan8,  700 },
    { Fan9,  800 },
};
#define N_FAN    (sizeof(fans)/sizeof(Fan_t))

void configure (
    int spd )
{
    Serial.print ("configure: ");
    Serial.println (spd);

    Fan_t  *f = fans;
    for (unsigned n = 0; n < N_FAN; n++, f++)  {
        byte cfg = spd >= f->spd ? OUTPUT : INPUT;
        pinMode (f->pin, cfg);

        Serial.print (f->pin);
        Serial.print ("  ");
        Serial.println (OUTPUT == cfg ? "OUTPUT" : "INPUT");
    }
}


void setup() {
    Serial.begin (115200);

    configure (390);
    configure (600);
    configure (800);
}

void loop() {
}

Even simpler would be:

const byte PINCOUNT = 9;
const byte PINS[PINCOUNT] = { 1,2,3,4,5,6,7,8,9 };

pinMode(PINS[0], OUTPUT);
for (byte i = 1; i < PINCOUNT; i++) pinMode(PINS[i], Fan_Speed >= i*100 ? OUTPUT : INPUT);
  Fan_Speed = constrain(as100.analogReadSmooth(Input_Fan_Speed), 395, 825);
  Fan_Speed = map(Fan_Speed, 395, 825, 0, 900);


  pinMode(Output_Fan1, OUTPUT);
  pinMode(Output_Fan2, (Fan_Speed >= 100) ? INPUT : OUTPUT);
  pinMode(Output_Fan3, (Fan_Speed >= 200) ? INPUT : OUTPUT);
  pinMode(Output_Fan4, (Fan_Speed >= 300) ? INPUT : OUTPUT);
  pinMode(Output_Fan5, (Fan_Speed >= 400) ? INPUT : OUTPUT);
  pinMode(Output_Fan6, (Fan_Speed >= 500) ? INPUT : OUTPUT);
  pinMode(Output_Fan7, (Fan_Speed >= 600) ? INPUT : OUTPUT);
  pinMode(Output_Fan8, (Fan_Speed >= 700) ? INPUT : OUTPUT);
  pinMode(Output_Fan9, (Fan_Speed >= 800) ? INPUT : OUTPUT);

Awesome job! Thanks very much everyone for your help, this is much much better. I still see the leds flickering a little when I am crossing each logic point if I move the dial slowly. Is there a way to try and reduce this behaviour and only have an LED on or off? I'm already using analoguesmooth set to 100 samples to try and reduce input noise.

why aren't you setting the output HIGH or LOW instead of changing the pin from an output to an input?

gcjr:
why aren't you setting the output HIGH or LOW instead of changing the pin from an output to an input?

I've done that before to emulate an "open collector / open drain" output. Switch to INPUT for high impedance and OUTPUT for Ground (I assume the pin has been written LOW somewhere).

I’m doing this because the existing PCB I’m trying to control from my car uses a system of earthing pins to light individual LEDs, so I found that setting the pin from input to output nicely controls the state. If I just set it to LOW/HIGH then the LED never fully turns of, it sort of ghosts.

450nick:
I still see the leds flickering a little when I am crossing each logic point if I move the dial slowly. Is there a way to try and reduce this behaviour and only have an LED on or off?

I would throw out the smoothing and use standard state change and debounce techniques.

  Fan_Speed = map(Fan_Speed, 395, 825, 0, 9);  // No need for 900 steps for 9 categories.

  static int previousFanSpeed = 0;
  static unsigned long lastFanSpeedChange = 0;
  if (Fan_Speed != previousFanSpeed && millis() - lastFanSpeedChange > 100)
  {
     previousFanSpeed = Fan_Speed;
     lastFanSpeedChange = millis();
     // Act on the speed change here
  }

The LEDs are dim when the outputs are HIGH? Are you putting 12V on the pins?

450nick:
I'm doing this because the existing PCB I'm trying to control from my car uses a system of earthing pins to light individual LEDs, so I found that setting the pin from input to output nicely controls the state. If I just set it to LOW/HIGH then the LED never fully turns of, it sort of ghosts.

Yes, this looks like you made a huge design error. Please post a wiring diagram. You can't "earth" anything directly from an Arduino pin, except for a permanent ground.

JCA34F:
The LEDs are dim when the outputs are HIGH? Are you putting 12V on the pins?

if the LEDs are driven from 12V and you need to pull them to ground to turn them on, applying 5V simply applies 7V across the LED circuit.

but if you could pull them to ground thru an open-collector circuit, there would be greater resistance when the transistor is not turned on, hence toggling the pin between OUTPUT-LOW and INPUT

i do the same on some keypad circuits

JCA34F:
The LEDs are dim when the outputs are HIGH? Are you putting 12V on the pins?

No the LEDs are fed by a 5V FET to a common rail that supplies the anodes of all of the LEDs. The cathodes then appear individually at a IDE male connector on the board - it's this that I am tying into with a ribbon cable to by arduino PCB. I looked for some earth switching transistor arrays and found one but it was discontinued - all the others I could find were source switching which won't work on this board unfortunately. This seems to work ok though as I'm using a Teensy 3.2.

aarg:
Yes, this looks like you made a huge design error. Please post a wiring diagram. You can't "earth" anything directly from an Arduino pin, except for a permanent ground.

It's not my design - it's PCB from my car, I have no idea why it is using earth switching on the LEDs but it does so I have to work with what's there as explained above. Normally this board plugs into a huge ECU that used to drive the dash but I'm replacing it with a single arduino. I'll post an image of what I've managed to deduce its wiring diagram as...

johnwasser:
I would throw out the smoothing and use standard state change and debounce techniques.

  Fan_Speed = map(Fan_Speed, 395, 825, 0, 9);  // No need for 900 steps for 9 categories.

static int previousFanSpeed = 0;
 static unsigned long lastFanSpeedChange = 0;
 if (Fan_Speed != previousFanSpeed && millis() - lastFanSpeedChange > 100)
 {
    previousFanSpeed = Fan_Speed;
    lastFanSpeedChange = millis();
    // Act on the speed change here
 }

Thanks John I will give this a try - I hadn't thought of using a debouncer but that's a great idea