Saturday, November 23, 2019

0000 0000 0001 0110

Counting the cost (74HC595 Shift Register...again...)

This week was supposed to be all about the most marvelous CD4026 chip, which I was going to use to count numbers outputting to a 7-segment display. The old favourite 555 timer (of course) was going to be on "clock" duties. But a funny thing happened on the way from China - the CD4026s arrived and had a sudden attack of being completely FAKE!!

To be honest I'm a little shocked because I have enjoyed such success with Chinese companies that it hurts when they send dodgy stuff (hurts them I mean). To rub salt into the wound it was the second lot of fake chips I received this week - the others being LM338 voltage regulators.

I'm getting my money back from AliExpress (hopefully - although they are good with their refund policy), but what I really would like back are the hours and hours of testing and trying to debug circuits which were never going to work in the first instance because of the fakery. Note to self (and anyone else watching) - never buy chips from Si Tai&SH IC accessories Store (CD4026) or shenzhen IC store (LM338). Shame on those guys.

So I've shelved the CD4026 blog for a later date (I have more chips on their way from a different source), and in the meantime and only because I'm so welded to the idea of a 7-segment counter I dragged out an old project which uses the Attiny13a microcontroller and a 74HC595 shift register to "fake" my own version of my own blog (the plot gets real thick about now).

As we've seen before the Attiny13 counts real well, and it also pumps out all the data needed to make the shift register drive not just LEDs but also in this case the patterns required for a 7-segment display (in this case common anode) to count hexidecimally from 0..F.

Here is the circuit:



And of course the Attiny13 needs a little code:


#include <avr/pgmspace.h>     // for reading the progmem values

#define DATA  (1<<PB0)        // pin 5
#define LATCH (1<<PB1)        // pin 6
#define CLOCK (1<<PB2)        // pin 7

// digit patterns for a 7-segment display
const PROGMEM uint8_t digit_pattern[17] =
{
  ~0b00111111,  // 0
  ~0b00000110,  // 1
  ~0b01011011,  // 2
  ~0b01001111,  // 3
  ~0b01100110,  // 4
  ~0b01101101,  // 5
  ~0b01111101,  // 6
  ~0b00000111,  // 7
  ~0b01111111,  // 8
  ~0b01101111,  // 9
  ~0b01110111,  // A
  ~0b01111100,  // b
  ~0b00111001,  // C
  ~0b01011110,  // d
  ~0b01111001,  // E
  ~0b01110001,  // F
  ~0b00000000   // quiet please
  
};

void setup() {

    DDRB = 0b00000111;  // set control pins as output
    PORTB = 0b00000000; // but be quiet to start with
    delay(10);
}

void shiftOut(uint8_t val)
{

    for(uint8_t i=0; i<8; i++) {

        if(val & 0b10000000) {
            PORTB |= DATA;
        }
        else {
            PORTB &= ~DATA;
        }
        // pulse the clock
        PORTB |= CLOCK;
        PORTB &= ~CLOCK;
       val<<=1; // move next bit
    }

    PORTB |= LATCH;
    PORTB &= ~LATCH;

}

void loop() {
        for(uint8_t msg=0; msg<17; msg++) {
            shiftOut(pgm_read_byte(&digit_pattern[msg]));
            _delay_ms(500);
        }
            _delay_ms(500); // extra delay before repeating cycle
}


Which just leaves us to breadboard the whole thing up and turn it on:





No comments:

Post a Comment