Arduino, shift registers and LEDs for a tacho

Hi to all,

I am in the process of building a dashboard for my racetrack motorbike. As rpm go up, more leds get lit.

From what i collected by googling here and there, i decided to go for an arduino uno to drive 40 leds through 5 shift registers (595)

So i got breadbord, resistors, leds and so on.

Got it to work fine with 8 leds and 1 shift register.
Got it to work fine with 16 leds and 2 shift register.

But i am now stuck with 24 leds and 3 shift registers.
One of my variables is successfuly incremented by bit shifting up to 32767 (var “leds” in code below)
But it goes crazy if one more bit is shifted into it… :confused:
I just dont get it. I declared that variable as int to start with and then turned it into unsigned long, but no success.
Serial.print shows that it all goes wrong above 2^15…

Here is my piece of code in case you can spot some obvious mistake… i did put together bits and bobs found on the internet…

Thanks a lot for your help

int rpmPin = 0; //pot connected here for now
int latchPin = 5;
int clockPin = 6;
int dataPin = 4;
int outputEnablePin = 3; //will be used to lower leds brightness as these are 5mm ultra bright!!!
 
unsigned long leds = 0;

void setup() 
{
  pinMode(latchPin, OUTPUT);
  pinMode(dataPin, OUTPUT);  
  pinMode(clockPin, OUTPUT);
  pinMode(outputEnablePin, OUTPUT);
  setBrightness(25);
  Serial.begin(9600);
}

void loop() 
{
  int reading  = analogRead(rpmPin);
  int numLEDSLit = reading / 42;  //1023
  if (numLEDSLit > 24) numLEDSLit = 24 ;
  leds = 0 ;
  for (int i = 0; i < numLEDSLit; i++)
  {
    leds = leds + (1 << i);  // sets the i'th bit
  }
  updateShiftRegister();
  delay(500);  
  Serial.print(numLEDSLit);
  Serial.print("  ");
  Serial.print  (leds);
  Serial.print("  ");
  Serial.println(leds,BIN);
}

void updateShiftRegister()
{
   digitalWrite(latchPin, LOW);
   shiftOut(dataPin, clockPin, LSBFIRST, (byte)leds);
   shiftOut(dataPin, clockPin, LSBFIRST, (byte)(leds >> 8) );
   shiftOut(dataPin, clockPin, LSBFIRST, (byte)(leds >> 16) );
   digitalWrite(latchPin, HIGH);
}

void setBrightness(byte brightness) // 0 to 255
{
  analogWrite(outputEnablePin, 255-brightness);
}

Hi,

Change this

leds = leds + (1 << i);

to

leds = leds + (1UL << i);

That should get you a little further. It will get you to 32 leds but not 40 in fact. The simplest way you can get to 40 with your current sketch will be to declare i as an “unsigned long long” and change that “1UL” to “1ULL”. Its all getting very inefficient, but what the hell, as long as it works…

If this was my project, I would probably use a max7219 to drive the (up to 64) leds. One chip replaces all 5 shift registers, and has a 16 level brightness control so you can dim the leds for riding at night. It also removes the need for all but one current limiting resistor, vs one resistor per led.

If the Arduino is not performing any other functions, I would transfer the sketch to an attiny85 to reduce the size (its an 8 pin chip).

Paul

Paul,

A very very big "thank you" !

Not only you found the exact missing bit, but you also think further AND you suggest how to get it better !!!

With all the 24 leds working, i now get some flickering, probably due to missing capacitor... i'll fix that asap

I just had a quick look on the max7219 controller... might be my next step, just need time to understand it all

Having a "unsigned long long" is not so clever to your point of view ? Wasting memory ? Big digit for a small task ?

I will be keeping my original arduino uno as it is also driving a 16x2 LCD for temp, oil pressure/temp and useful settings (tweeking value of redzone flashlight, ...). It could also be reading sensors (fork travel,...) and getting the data on an SDcard... :)

I will be posting more of that project as it comes through, if people dont mind...

Thanks again for your precious help.

In that case I would recommend a Nano 3, Pro Mini or Pro Micro for the finished project. Use your Uno for development for now, and on your next project.

What interface does that lcd have? The basic ones will need 6 Arduino pins, but all but one could potentially be shared with other devices like the max7219. Often with multiple devices connected to multiple Arduino outputs, pins can be shared because each device has a "load"/"enable" pin which is the only one that needs to be dedicated to that device alone. (Hope that explanation makes sense! )

Your sd card will have to be connected to the SPI bus outputs of the Arduino. The max7219 can also be connected to SPI. You could even use a 74hc595, also connected to the spi bus, to drive the lcd, although that introduces an extra chip, so an idea to avoid unless you are running out of Arduino outputs.

Thanks a lot

I keep those in mind to save my Arduino for later !

LCD uses I2C, pretty clever thing. It even has got buttons on it, useful to navigate through menus ("case" operator, to select and store options such as brightness, threshold for shiftlight, and so on)

Your explanation makes sens about communication buses and how to enable devices to enter in "listen mode" :)

Could i mix SPI and I2C on the same Arduino board ?

Yes, spi and i2c busses use different pins.

So, you have sd card and max7219 on spi bus and your lcd on i2c bus. No too many pins used so far. Both busses can connect to multiple devices.

If you need more help, do post links to each component you have, or preferably to those you are considering, before you purchase. The forum can advise suitability.

what is a "shiftlight", an led to tell you when to change gear? If so, won't your led tacho tell you when to do this? (I know little about racing bikes).

Paul,

Thank you very much for your offer of giving (more) advice !

OK for I2C and SPI. That means my likkle Arduino can run both busses at the same time ? Wouldn't this overload it ?

ShiftLight is a strong and fast flashing LED that indicate the shift optimal rpm (in my case) or when entering red zone... I can set that rpm through the LCD and pushbuttons.

Thanks again, you made that projet go further !

ben999: OK for I2C and SPI. That means my likkle Arduino can run both busses at the same time ? Wouldn't this overload it ?

Your "likkle" Arduino can perform 16 million operations every second. It only has a single processor core, so in reality it only ever does one thing at once, but it can do them so fast they appear simultaneous, to us slow humans. You may be thinking your PC is 3GHz+ and quad cores, but that has the massive overhead of operating systems, hi-res graphics, hard drives, network interfaces, blah, blah, none of which Arduino has to deal with. You will find 16MHz is actually way faster than you need for your project.

XD couldn't agree more... where is all that power going in todays computers !!!

Likkle Arduino is a friendly name for that piece of fun !!!

On the serious side : i found a Nano V3 (Atmega 328, following your advice... really small!!!) on THE famous auction site... price is ridiculously low... fake one ?

Probably "clone" is more accurate than "fake". I believe Arduino is open-source hardware, so anyone can legally make them. Not sure they are allowed to call them "Arduino", but "Arduino clone" is acceptable. (Anyone please correct me on this as necessary)

Pro Micro and Pro Mini are smaller still. (You need a usb/serial adaptor for Pro Mini).

I prefer Nano 3 and Pro Micro to "regular" Arduino like Uno and use them for all my projects, because I like to prototype using breadboards, and find them much more convenient for that. If you want to use shields, then Uno/Mega is the way to go.