0

I am using a port of the Arduino libraries on an AtTiny85 (1MHz) to drive a 4-digit 7-segment LED (common cathode, 12-pin). I'm just counting from 0 to 9 and alternating between the first two digits (pin 12 and 9) as a test. I am driving from two 74HC595N shift registers in series, the first of which will trigger S9018 NPN BJT transistors to turn on/off the digit I want and the other to light the segments.

The code seems to work fine, functionally, to alternate the two digits, but they don't alternate fast enough to make the LED show two solid digits, instead you can clearly see them flashing/alternating. Not sure what the bottleneck is but here's the code (please ignore my wiring for the 7 segments)

// CONFIGURATION
// Pins
const int latchPin = 2;
const int clockPin = 4;
const int dataPin = 3;

// Timers
const long output_interval = 10000; // Time to change each output 
const int T_digit = 2; //period on one digit (4 digit 7-segment only)
const int duty_digit = 1; // duty cyle of a digit shown

// States
unsigned long outputT_last = 0; // Holds the last time output change was checked
unsigned long outputT_now = 0;
bool fourDigit7Segment_enable = true; // set if we are using 4 digit 7 segment led

// States
byte leds = 0;
byte digits = 0;

int output_count=0;

void setup() 
{
  pinMode(latchPin, OUTPUT);
  pinMode(dataPin, OUTPUT);  
  pinMode(clockPin, OUTPUT);
}

void loop() 
{
  checkOutput();
}

void updateShiftRegister()
{
  digitalWrite(latchPin, LOW); // Gets latch ready by setting to low since we need a rising edge to trigger
  if(fourDigit7Segment_enable){
    int digitON = (int)(outputT_now - outputT_last);
    digits = 0;
    if(digitON%T_digit < duty_digit){
      //bitwrite led 0
      bitWrite(digits, 0, 1);
    }
    else{
      //bitwrite led 1
      bitWrite(digits, 1, 1);
    }
    //shift out digit control first in LSB
    shiftOut(dataPin, clockPin, MSBFIRST, digits); // shiftOut will write to dataPin and trigger a rising on clickPin at same time while writing byte value from leds var
  }
  shiftOut(dataPin, clockPin, MSBFIRST, leds); // shiftOut will write to dataPin and trigger a rising on clickPin at same time while writing byte value from leds var
  digitalWrite(latchPin, HIGH); // Trigger with rising edge
}

void clearMemory(){
  leds = 0;
  updateShiftRegister();
}

void checkOutput(){
  outputT_now = millis();
  float timeleft = (int)((outputT_now - outputT_last)/1000);
  if (outputT_now - outputT_last >= output_interval){
    outputT_last = outputT_now; // output_interval set to 10000, because LED counts 0 to 9, and then needs to reset
  }
    // clearMemory(); // Uncomment this if you want 1 LED lit at time, all others turned off
    leds = sevenSegment1D(timeleft);
    updateShiftRegister();
    // output_count++;
  // }
  // Check if we reach the end, then do 1 more iteration for 0x0 (all turned off)
  // if(output_count > 8){
    // output_count=0;
    // clearMemory();
  // }
}

byte sevenSegment1D(int i){
  switch (i) {
      case 0:
        return 0x7E; //01111110
        break;
      case 1:
        return 0x48; //01001000
        break;
      case 2:
        return 0x3D; //00111101
        break;
      case 3:
        return 0x6D; //01101101
        break;
      case 4:
        return 0x4B; //01001011
        break;
      case 5:
        return 0x67; //01100111
        break;
      case 6:
        return 0x77; //01110111
        break;
      case 7:
        return 0x4C; //01001100
        break;
      case 8:
        return 0x7F; //01111111
        break;
      case 9:
        return 0x6F; //01101111
        break;   
      default:
        return 0x0; //Arduino doesn't handle bytes in binary
  }
}

I tried to mod a float but it seems to require an int, so that's why I stopped at 2%1. I also converted the code from a single-digit 7-segment LED so please ignore anything that doesn't make sense in lighting up the segments.

I am not sure if the bottleneck is my code, the 1MHz AtTiny85, or the shift register.

EDIT: switched over to micros() instead of using millis() for more resolution. Still not solid.

  • Did you pick a board entry that specifies 1MHz? – Ignacio Vazquez-Abrams Mar 16 '15 at 3:37
  • I am unsure how to check this. – PGT Mar 16 '15 at 3:41
  • Did you try looking at the board entry? – Ignacio Vazquez-Abrams Mar 16 '15 at 6:06
  • Can't you just lower T_digit? Better would be to use a timer to update the digits every X ms. That way the main loop doesn't interfere with the display update. 1mHz should be fast enough to get at least 60hz update speed. – Gerben Mar 16 '15 at 14:22
  • Turns out there is something wrong with my mod calculation. I did a test with to shift out the first digit, reset, then shift out another with delay(2) and it's solid. – PGT Mar 16 '15 at 23:56
0

The original idea was to divide up a specific period into segments where each digit on the 4-digit 7-segment would light up. I would use a mod(%) and divide it up to make the function call more generic for future extensibility (and also make it more asynchronous). What I learned is that it would probably take more work doing the calculations then just calling a function to reset and light up the next digit one after another. Here's the updated code:

// CONFIGURATION
// Pins
const int latchPin = 2;
const int clockPin = 4;
const int dataPin = 3;

// Timers
const int countdown = 60; // amount of time to countdown from in seconds
const long reset_interval = countdown*1000000; // interval before reset in microseconds, i.e. if countdown is set to 60s, every 60 seconds will reset display to countdown start

// States
unsigned long last_display_update_time = 0; // Holds the last time output change was checked
unsigned long curr_time = 0;
bool fourDigit7Segment_enable = true; // set if we are using 4 digit 7 segment led

// States
byte leds = 0;
byte digits = 0;

int output_count=0;

void setup() 
{
  pinMode(latchPin, OUTPUT);
  pinMode(dataPin, OUTPUT);  
  pinMode(clockPin, OUTPUT);
}

void loop() 
{
  updateResetTimer(); // checks what the countdown is at
  int timeleft = countdown - (curr_time - last_display_update_time)/1000000;
  leds = getSevenSegmentFormation(timeleft/10);
  updateShiftRegister(0);
  leds = getSevenSegmentFormation(timeleft%10);
  updateShiftRegister(1);
}

void updateShiftRegister(int digit)
{
  digitalWrite(latchPin, LOW); // Gets latch ready by setting to low since we need a rising edge to trigger
  if(fourDigit7Segment_enable){
    int digitON = micros();
    digits = 0;
    bitWrite(digits, digit, 1);
    //shift out digit control first in LSB
    shiftOut(dataPin, clockPin, MSBFIRST, digits); // shiftOut will write to dataPin and trigger a rising on clickPin at same time while writing byte value from leds var
  }
  shiftOut(dataPin, clockPin, MSBFIRST, leds); // shiftOut will write to dataPin and trigger a rising on clickPin at same time while writing byte value from leds var
  digitalWrite(latchPin, HIGH); // Trigger with rising edge
}

//Turns off all 7 segments of a digit, will need to specify digits 0 to n
void clearMemory(int i){
  leds = 0;
  updateShiftRegister(i);
}

//Updating timer for resetting countdown
//Will take absolute current time and compare it to the last time checked, if it is greater than countdown value, we reset
void updateResetTimer(){
  curr_time = micros();
  if (curr_time - last_display_update_time >= reset_interval){
    last_display_update_time = curr_time; // reset_interval set to 10000000, because LED counts 0 to 9, and then needs to reset // actually set to 60*1000000 to countdown 1 minute
  }
}

byte getSevenSegmentFormation(int i){
  switch (i) {
      case 0:
        return 0x7E; //01111110
        break;
      case 1:
        return 0x48; //01001000
        break;
      case 2:
        return 0x3D; //00111101
        break;
      case 3:
        return 0x6D; //01101101
        break;
      case 4:
        return 0x4B; //01001011
        break;
      case 5:
        return 0x67; //01100111
        break;
      case 6:
        return 0x77; //01110111
        break;
      case 7:
        return 0x4C; //01001100
        break;
      case 8:
        return 0x7F; //01111111
        break;
      case 9:
        return 0x6F; //01101111
        break;   
      default:
        return 0x0; //Arduino doesn't handle bytes in binary
  }
}
| improve this answer | |

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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