I've wrote a speedo program using a hall effect that then drives 3 x 7 segment display via 3 x CD4511 decoders.
The code works well except the write to the displays is slow and they flash about every 1/2 second.
It is the speedo subroutine (that senses the hall) that is slowing it down because if I run the 7 segment code from an analogue voltage the display 'appear' to stay on and change quickly when the anslog volts changes.
I need to make this as fast as possible as it is part of a much larger program.
Any suggestions gratefully received.
// the start of the BCD pins used for ABCD must be sequential
int BCDStart = 43;
// the start of the common pins - must be sequential
int commonStart = 47;
// this code can use either polarity of display.
// true if common is high when ON, otherwise false. Using common cathode = false
boolean commonHigh = false;
// the analog input for the potentiometer or use value from hall OP code
int hall_pin = A4;
float hall_thresh = 10.0;
int wheelCirc = 1000;
int KMHour = 0;
// the number of digits your display has.
int noOfDigits = 3;
void setup() {
// Enable all bcd outputs,
// set them to OFF
for(int i=0;i<4;++i)
{
pinMode(BCDStart + i, OUTPUT);
pinMode(hall_pin, INPUT);
digitalWrite(BCDStart + i, commonHigh?1:0);// If commonHigh is true (its false) set all pins to 1 else set to 0. Common cathode needs 0 (1 fires segment).
}
for(int i=0;i<noOfDigits;++i)
{
pinMode(commonStart + i, OUTPUT);
digitalWrite(commonStart + i, commonHigh?0:1);
}
Serial.begin(9600);
}
void loop() {
speedo();
int amount = KMHour;
if (amount <99)
{
noOfDigits = 2;
}
else
{
noOfDigits = 3;//turns of funwanted digits
}
for(int i=(noOfDigits -1);i>=0;--i) {
// find the current digit, which is in the low 4 bits. first pass is right display on, second pass swithches to left display.
int digit = amount % 10;
// and write out the representation of the voltage
writeDigitToDisplay(digit);// first send remainder to function then 2nd pass send 10's to function
// enable the correct digit for display
digitalWrite(commonStart + i, commonHigh?1:0);//writes each returned bit of remainder to right display.
// short delay between changes.
delay(1);
// Turn off the correct digit for display
digitalWrite(commonStart + i, commonHigh?0:1);
// get the next digit.
amount = amount / 10;// finds 10's value and rerun For to initiate middle display
// Turn off the correct digit for display
digitalWrite(commonStart + i, commonHigh?0:1);
}
}
// Now we define the bits that are on and off
// for ABCD output, These are used in the
// function below to generate the BCD for the 4511.
int dig[10] = {
0b0000,//0
0b0001,//1
0b0010,//2
0b0011,//3
0b0100,//4
0b0101,//5
0b0110,//6
0b0111,//7
0b1000,//8
0b1001,//9
};
void writeDigitToDisplay(int digit) {
for(int i=0;i<4;++i)
{
// isolate the current bit in the loop.
int currentBit = (1<<(i)); //shifts binary 0001 by 3-i. CurrentBit is 4 new combinations (as i changes)or reverse LSB read as (1<<(i))
// check if the bit is on, and invert for
// commonhigh if needed.
int bitOn = (currentBit&digit)!=0;//if currentBit & digit then 3-1 is 1
if(commonHigh) {//is false
bitOn = !bitOn;//so bitOn stays at 1
}
// and lastly set the bit
digitalWrite(BCDStart+i, bitOn); //writes bitOn to each BCD pin
}
}
void speedo()
{
float hall_count = 1.0;
float start = micros();
bool on_state = false;
// counting number of times the hall sensor is tripped
// but without double counting during the same trip
while(true)
{
if (digitalRead(hall_pin)==0){//every time hall is switched to 0 run if
if (on_state==false){//already set to false so make true
on_state = true;
hall_count+=1.0;//count = (hall_count + 1.0) + new value of hall_count
}
} else{
on_state = false;
}
if (hall_count>=hall_thresh)
{
break;
}
}
float end_time = micros();
float time_passed = ((end_time - start)/1000000.0);
float rpm_val = (hall_count/time_passed)*60.0;
KMHour = (((wheelCirc * rpm_val)/1000000)*60);
Serial.println(KMHour);
}