Go Down

Topic: 'High' voltage 7-seg LED interface (Read 3671 times) previous topic - next topic

smartroad

That worked!! I now have it counting from 00 to 99 :)

Annoyingly and stupidly, I mananged to under order the resistors so I can't do more then 2 displays at the moment. Dead chuffed that it is working as planed at the moment. Next job is to try and get it to work on the larger displays now with the different voltages.

http://www.youtube.com/watch?v=hgjT3OJ07HA

Mr. Swarf

I don't know about anybody else but I cannot view your Y-T videos as they are labeled as 'private'.
M.S.

smartroad

Ooops meant to put them up simply as unlisted [smiley=embarassed.gif] not private. Changed now! :)

BTW they aren't anything exciting, I am just a little proud that with the help of these guys that it actually works. Normally I have a great idea then can't figure out how to make it function!

I am hoping to find a way of making a library to make it easier to display using shift-reg's as I am not aware of one. Plus makes it easier it implement on any future projects I may have.

smartroad

Okay so have everything wired up and it is working - sort of.

I seem to be getting a 'shadowing' across the displays. The following should be displaying 230:


And it is, however it also seems to be showing the previous digits as well. The camera doesn't pick up the light differences too well. You can see that there is a 230 displayed as they are brighter. The remaining LEDs are at about 25-50% brightness.

As far as I can figure this is an issue with the way that I am using the shift registers with a common cathode display, as suggested by Graynomad. I can't use the G line to blank the display while updating (if G goes high to blank the display all the outputs switch off thus actually turning on all the LEDs), so you are seeing the effect of the other numbers being pushed down the shift registers.

The only other way I can think of is to cut power to the GND of the displays as the screen updates using a transistor. I was hoping though that someone else may have an alternative solution that could be applied in software.

For those interested here is a picture of the minute board:

smartroad

Solved the ghost problem. Have put a transistor into the ground line for the displays. Now the Adruino can turn off the displays while it updates. Only downside is a reduction in brightness. Have to wait until tomorrow to see how that affects the readability in daylight.

Mr. Swarf

Thanks. I have a project coming up with higher voltage LED displays so I am watching this.

:)
M.S.

Graynomad

I did say that the idea was

Quote
Off the top of my head mind, I haven't tried it but it should work

but I still reckon it should work without without having to turn the displays off.

Are you sure you're only latching the SRs at the end of the data stream?

Can you post the actual circuit and code?
Rob Gray aka the GRAYnomad www.robgray.com

smartroad

Sorry Graynomad, just re-read my post and didn't meant to sound like I was blaming you! I am enjoying the challenge :D

I'll get a circuit and the code up tomorrow (well later today as it is 12.30am  ;D). Code is still a little messy at the moment, but will put it up in current state.

smartroad

#23
Aug 03, 2010, 09:42 am Last Edit: Aug 03, 2010, 09:51 am by smartroad Reason: 1
Here is the circuit diagram. Each display is the same.




Code (once I have it all working correctly I plan to tidy this up a lot, just want to fix one problem at a time). I borrowed the button check function for testing for a long press (sorry can't remember where on the web I found it  :-[). The clock came from Rob Faludi and his open source clock.

Code: [Select]

/*
Count Down Timer

Usage - Three buttons: Mode, Hour and Minute.

Short press Mode = Start/Pause timer
Long press Mode (2.5sec) = Enter/exit timer setting mode

With timer paused press Minute and Hour together to reset clock

In Timer Setting mode, press Hour/Minute to increment time settings.

*/

#define timeroffest -3 //adjustment for error in timing

#define resetPin 8
#define minutePin 9
#define hourPin 10

#define debounce 50                       // ms debounce period to prevent flickering when pressing or releasing the button
#define holdTime 2500                     // ms hold period: how long to wait for press+hold event

#define Tserial 4
#define Tclk 6
#define Trck 5
#define dBlank 7  // pin to blank display - low = display off - high = display on

byte character[10] = {
 B01000010, B11101110, B11000001, B11000100, B01101100, B01010100, B01010000, B11001110, B01000000, B01001100};

boolean runMode = false;
boolean setMode = false;
boolean run=0, reset=0;

int second=0, minute=0, hour=0; // declare working time variables

int sMin=30, sHour=2; //declare set time variables



void setup() {
 pinMode(resetPin, INPUT); //pins for normally closed switches to set the time
 pinMode(minutePin, INPUT);
 pinMode(hourPin, INPUT);
 digitalWrite(resetPin, HIGH); // writing an input high turns on pull-up resistors
 digitalWrite(minutePin, HIGH);
 digitalWrite(hourPin, HIGH);

 pinMode(Tserial, OUTPUT);
 pinMode(Tclk, OUTPUT);
 pinMode(Trck, OUTPUT);
 pinMode(dBlank, OUTPUT);

 digitalWrite(Trck, LOW);
 digitalWrite(dBlank, LOW);

 minute = sMin;
 hour = sHour;
}

void loop() {

 if (second == 0 && minute == 0 && hour == 0 || runMode == 0) {
   if (setMode == false) displayOut(false);
 }
 else if (setMode == false) {
   clock();
   displayOut(false);
 }

 if (setMode == true) {
   setTime();
   displayOut(true);
 }

 if (runMode == 0 && reset == 1) {
   second =0;
   minute = sMin;
   hour = sHour;
   reset = 0;
 }


 checkButtons(); // runs a function that checks the setting buttons
}














void setTime() {
 static boolean minStat = false, hrStat = false;
 int minBut, hrBut;

 minBut = digitalRead(minutePin);
 hrBut = digitalRead(hourPin);

 if (hrBut == LOW && hrStat == false) {
   sHour = sHour + 1;
   if (sHour > 9) sHour = 0;
   hrStat = true;
 }
 if (hrBut == HIGH && hrStat == true) {
   hrStat=false;
 }

 if (minBut == LOW && minStat == false) {
   sMin = sMin + 1;
   if (sMin > 59) sMin = 0;
   minStat = true;
 }
 if (minBut == HIGH && minStat == true) {
   minStat=false;
 }

 hour = sHour;
 minute = sMin;
 second = 0;
}




void checkButtons() {

 static long btnDnTime;                           // time the button was pressed down
 static long btnUpTime;                           // time the button was released
 static boolean ignoreUp = false;                 // whether to ignore the button release because the click+hold was triggered
 static int R = 0;                                 //Mode button state
 static int Rstate = 0;

 R = digitalRead(resetPin);                   //read Mode button state    
 //Test for button pressed and store the down time
 if (R == LOW && Rstate == HIGH && (millis() - btnUpTime) > long(debounce))
 {
   btnDnTime = millis();
 }
 //Test for button release and store the up time
 if (R == HIGH && Rstate == LOW && (millis() - btnDnTime) > long(debounce) && setMode == false)
 {
   if (ignoreUp == false) runMode = !runMode;      //test if Low-High set mode should be toggled
   else ignoreUp = false;
   btnUpTime = millis();
 }
 //Test for button held down for longer than the hold time
 if (R == LOW && (millis() - btnDnTime) > long(holdTime))
 {
   setMode = !setMode;                  //toggle Set mode to Timing mode or vice versa
   runMode = 0;
   ignoreUp = true;
   btnDnTime = millis();
 }
 Rstate = R;

 if (runMode == 0) {
   if (digitalRead(minutePin) == LOW && digitalRead(hourPin) == LOW) reset = 1;
 }

}




void clock() {
 static unsigned long lastTick = 0; // set up a local variable to hold the last time we moved forward one second
 // (static variables are initialized once and keep their values between function calls)

 // move forward one second every 1000 milliseconds
 if (millis() - lastTick >= 1000+timeroffest) {
   lastTick = millis();
   second--;
 }

 // move back one minute every 60 seconds
 if (second < 0) {
   minute--;
   second = 59; // reset seconds to zero
 }

 // move back one hour every 60 minutes
 if (minute < 0) {
   hour--;
   minute = 59; // reset minutes to zero}
 }

 if (hour < 0) {
   hour = 0; // reset hours to zero
 }

}




void displayOut(boolean set) {
 byte output;
 byte minH;
 byte minL;
 byte hourL;
 static byte secFlash, secReg;
 static unsigned long update = 0;

 if (millis() - update >= 100) {
   
 hourL = hour;
 minH = minute / 10;
 minL = minute % 10;

 digitalWrite(dBlank, LOW);

 output = character[minL];

 if(setMode==true) {
   bitClear(output, 6);
 }

 for(int c=0; c<=7; c++)
 {
   digitalWrite(Tserial, bitRead(output, c));
   digitalWrite(Tclk, HIGH);
   digitalWrite(Tclk, LOW);
 }

 output = character[minH];
 for(int c=0; c<=7; c++)
 {
   digitalWrite(Tserial, bitRead(output, c));
   digitalWrite(Tclk, HIGH);
   digitalWrite(Tclk, LOW);
 }
 digitalWrite(Trck, HIGH);
 digitalWrite(Trck, LOW);

 output = character[hourL];
 
 if (secFlash != second) {
   secReg = !secReg;
   secFlash = second;
 }
 
 bitWrite(output, 6, secReg);
 
 for(int c=0; c<=7; c++)
 {
   digitalWrite(Tserial, bitRead(output, c));
   digitalWrite(Tclk, HIGH);
   digitalWrite(Tclk, LOW);
 }
 digitalWrite(Trck, HIGH);
 digitalWrite(Trck, LOW);

 digitalWrite(dBlank, HIGH);
 }
}

Graynomad

Got that, I'm about to have dinner but two things that look a little suss in the displayOut function are

Code: [Select]
 for(int c=0; c<=7; c++)
 {
   digitalWrite(Tserial, bitRead(output, c));
   digitalWrite(Tclk, HIGH);
   digitalWrite(Tclk, LOW);
 }
 digitalWrite(Trck, HIGH);
 digitalWrite(Trck, LOW);


Won't this produce 9 pulses on Trck?

and

Code: [Select]
 bitWrite(output, 6, secReg);
The DP is connected to bit 7, doesn't this set bit 6?

I'll have a closer look later tonight.

Rob
Rob Gray aka the GRAYnomad www.robgray.com

smartroad

Trck is outside of the for loop so should only pulse once after each loop completion. Thinking about that, I should only need to toggle Trck at the end of the display run rather then after each loop.

Ignore the pins connections between the IC and LED. I had to adjust the pin connections on the breadboard to keep the wiring simple. Bit 6 is the DP on the prototype.

smartroad

Ahhh solved brightness issue.

Where I had added the blanking for the display at the beginning of the displayout, i also added a delay to reduce the number of times it updated the display.

Code: [Select]
if (millis() - update >= 500) {

I forgot to update "update" with the current millis() value when the IF statement was true. So it updated the screen every time it was run.

smartroad

@Mr. Swarf

Glad to help :) I would strongly suggest that you use common anode though, makes it much easier!

Graynomad

Quote
Trck is outside of the for loop

Oops, didn't notice the different spelling.

Quote
Thinking about that, I should only need to toggle Trck at the end of the display run rather then after each loop.


That's right.

I found the code difficult to read and a bit long-winded with local variables that really didn't do anything, so can I suggest something like this

Code: [Select]
#define DP_BIT B01000000

void displayOut() {

 byte dp_bit = 0;

 static byte secFlash;
 static unsigned long update = 0;

 if (millis() - update >= 100) {
   
         if (secFlash != second) {
           dp_bit ^= DP_BIT;     // toggle the DP bit
           secFlash = second;
       }

       outputChar(character[minute / 10]);
       outputChar(character[minute % 10]);
       outputChar(character[hour] != dp_bit);
       
       digitalWrite(Trck, HIGH);      // latch data to OPs
       digitalWrite(Trck, LOW);
 }
}
 

void outputChar(byte c) {
     for(int i=0; i<=7; i++) {
           digitalWrite(Tserial, bitRead(c, i));
           digitalWrite(Tclk, HIGH);
           digitalWrite(Tclk, LOW);
     }
}


I haven't seriously researched your routine or tested this but am sure this will do the same. You shouldn't need to blank the display.

Also, I think it's fair to say that normal coding practice is to UPPER_CASE any constants (#defines), that way when you look at a piece of code you know that for example HOLD_TIME is a constant and you don't go looking for it's declaration or any code that changes it.

Quote
I would strongly suggest that you use common anode though, makes it much easier

I second that  :)

Rob
Rob Gray aka the GRAYnomad www.robgray.com

smartroad

That works. Had to change
Code: [Select]
outputChar(character[hour] != dp_bit); to
Code: [Select]
outputChar(character[hour] ^= dp_bit); to get it to work.

However it now seems to turn the DP on minute/10 follows the hour DP a fraction of a second after. It is only the "/10" not the "%10"

Go Up