4 bit binary clock

Hello, im attempting a project that uses a 4 bit binary clock from the arduino.
originally, I was trying to use ttl chips like the 74161 but everytime something very random and weird would happen even though everything is wired correctly. So I gave up on that. I remembered I had an arduino laying around but hadn't gotten to use it yet.
I want to use the arduino to act as a 4 bit binary clock. This would then feed into a 74141 chip which decodes into 0-9. This vintage chip is used to power nixie tubes which I already have, as well as built the 180v power supply for them.

So I can't find a working code for a 4 bit binary. Since my primary goal is the building of the circuit, im hoping I don't have to learn to code quite yet. I made a 1hz crystal oscilator if that helps. Can anyone help me out finding code for it?

You just want to output this pattern with 1 second updates?
0000
0001
0010
0011
0100
0101
0110
0111
1000
1001
repeat

that's exactly it. However there has to be 6 counters basically. For 6 digits. The display will not be binary, I just need the binary to use the high voltage decoder chips.

So the 1seconds reset at 1001 (9)
the 10seconds resets at 0101 (5)
the 1minutes reset at 1001 (9)
the 10minutes reset at 0101 (5)
The 1 hour resets at 0010 (2) IF 10hours is 1, and 1001 (9) if 10hours is 0
the 10hours reset at 0001 (1)

That would mean I need 19 pins and the arduino only has 13. If I HAVE to (not ideal) I can go with only minutes and hours as that uses 12 pins.

But I still need to find code that works. And preferrably a 12 hour clock one. Hrmm. The one I tried counted way to fast and only worked on the first "counter" or "digit"

ATMega328 based Arduino has 20 IO pins, A0-A5 are addressed as D14-D19.
Counting up is pretty straightforward to my hardware design way of thinking.
seconds_ones 4 IO 0000 to 1001
seconds_tens 3 IO 000 to 101
minutes_ones 4 IO 0000 to 1001
minutes_tens 3 IO 000 to 101
hours_ones 4 IO 000 to 1001
hours_tens 2 IO 00 to 10
Total: 20
Have to do something on power up, read a button or something, and decide whether to go into time program mode.

// define pins needed, variables used below, etc.
byte seconds_ones = 0;   // etc for other variables

unsigned long currentMillis;
unsigned long previousMillis;
void setup(){
// set pins as outputs
}
void loop(){
currentMillis  = millis();
if ( (currentMillis >= (previousMillis +1000UL){
previousMillis = previousMillis +1000UL;
seconds_ones = seconds_ones+1;
if (seconds_ones == 10){
  seconds_ones = 0;
  seconds_tens = second_tens +1;

if (seconds_tens ==6){
  seconds_tens = 0;
  minutes_ones = minutes_ones +1;
}
if (minutes_ones ==10){
  minutes_ones = 0;
  minutes_tens = minutes_tens+1;
}
if (minutes_tens == 6){
  minutes_tens = 0;
  hours_ones = hours_ones+1;
}
if (mode ==12 && hours_ones == 3){ // 12 hour mode example, do similar for 24
  hours_ones = 0;
  hours_tens = hours_tens +1;
}
if (mode == 12 && hours_tens ==2){  // 12 hour mode example, do similar for 24
  hours_tens = 0;
}
// now write the data out
// bit of a brute force method
// call each digit d,c,b,a
// seconds_ones:
digitalWrite (seconds_ones_pin_d, seconds_ones & B1000); // non-zero will be High, zero will be Low
digitalWrite (seconds_ones_pin_c, seconds_ones & B0100);
digitalWrite (seconds_ones_pin_b, seconds_ones & B0010);
digitalWrite (seconds_ones_pin_a, seconds_ones & B0001);
//mimic for the other digits

} // end 1 second check
} // end void loop

What about multiplexing ? Use 10 pins, 4 for the data, 6 for the digit select. My idea is : use 6 - 74141 - BCD-decimal, 6 "4 bit latch" chip. Connect the data D3,D2,D1,D0 as a "bus" going to the input of the 4 bit latch chip, the output of the latch chip going into the input of the 74141. The rest is the "select" of the digit. In the program, data - seconds - select digit 1, until data - 2nd hour - select digit 6.

Or simpler: just use 3 8-bit shift registers, each drives two 74141 chips for two tubes.
Frees up lots of pins for other stuff, like buttons for setting the time.

Oh gosh, what have I gotten myself into! I was looking through the code and it the language definately looks fairly straight forward.

This is the code I quickly uploaded to test the idea. I'm going to set it up again and try it again but last time it counted so weirdly and far to fast. I think it's meant for only hour and minute display though, as well as it being 24 hours but the 24 vs 12 hours can be relatively easily changed.

/*
An open-source binary clock for Arduino. 
Based on the code from by Rob Faludi (http://www.faludi.com)
Code under (cc) by Daniel Spillere Andrade, www.danielandrade.net
http://creativecommons.org/license/cc-gpl
*/

int second=0, minute=0, hour=0; //start the time on 00:00:00
int munit,hunit,valm=0,valh=0,ledstats,i;

void setup() { //set outputs and inputs
pinMode(1, OUTPUT);pinMode(2, OUTPUT);pinMode(3, OUTPUT);pinMode(4, OUTPUT);pinMode(5, OUTPUT);
pinMode(6, OUTPUT);pinMode(7, OUTPUT);pinMode(8, OUTPUT);pinMode(9, OUTPUT);pinMode(10, OUTPUT);
pinMode(11, OUTPUT);pinMode(12, OUTPUT);pinMode(13, OUTPUT);

pinMode(0, INPUT);
}

void loop() {

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) {
  lastTick = millis();
  second++;

}

// move forward one minute every 60 seconds
  if (second >= 60) {
  minute++;
  second = 0; // reset seconds to zero
}

// move forward one hour every 60 minutes
if (minute >=60) {
  hour++;
  minute = 0; // reset minutes to zero
}

if (hour >=24) {
  hour=0;
  minute = 0; // reset minutes to zero
}

  munit = minute%10; //sets the variable munit and hunit for the unit digits
  hunit = hour%10;


  ledstats = digitalRead(0);  // read input value, for setting leds off, but keeping count
  if (ledstats == LOW) {
    
  for(i=1;i< =13;i++){
  digitalWrite(i, LOW);}
  
  } else  {

  //minutes units
  if(munit == 1 || munit == 3 || munit == 5 || munit == 7 || munit == 9) {  digitalWrite(1, HIGH);} else {  digitalWrite(1,LOW);}
  if(munit == 2 || munit == 3 || munit == 6 || munit == 7) {digitalWrite(2, HIGH);} else {digitalWrite(2,LOW);}
  if(munit == 4 || munit == 5 || munit == 6 || munit == 7) {digitalWrite(3, HIGH);} else {digitalWrite(3,LOW);}
  if(munit == 8 || munit == 9) {digitalWrite(4, HIGH);} else {digitalWrite(4,LOW);}

  //minutes 
  if((minute >= 10 && minute < 20) || (minute >= 30 && minute < 40) || (minute >= 50 && minute < 60))  {digitalWrite(5, HIGH);} else {digitalWrite(5,LOW);}
  if(minute >= 20 && minute < 40)  {digitalWrite(6, HIGH);} else {digitalWrite(6,LOW);}
  if(minute >= 40 && minute < 60) {digitalWrite(7, HIGH);} else {digitalWrite(7,LOW);}

  //hour units
  if(hunit == 1 || hunit == 3 || hunit == 5 || hunit == 7 || hunit == 9) {digitalWrite(8, HIGH);} else {digitalWrite(8,LOW);}
  if(hunit == 2 || hunit == 3 || hunit == 6 || hunit == 7) {digitalWrite(9, HIGH);} else {digitalWrite(9,LOW);}
  if(hunit == 4 || hunit == 5 || hunit == 6 || hunit == 7) {digitalWrite(10, HIGH);} else {digitalWrite(10,LOW);}
  if(hunit == 8 || hunit == 9) {digitalWrite(11, HIGH);} else {digitalWrite(11,LOW);}

  //hour
  if(hour >= 10 && hour < 20)  {digitalWrite(12, HIGH);} else {digitalWrite(12,LOW);}
  if(hour >= 20 && hour < 24)  {digitalWrite(13, HIGH);} else {digitalWrite(13,LOW);}

  }

  valm = analogRead(0);    // add one minute when pressed
   if(valm&lt;800) {
   minute++;
   second=0;
   delay(250);
  }
  
  valh = analogRead(5);    // add one hour when pressed
   if(valh&lt;800) {
   hour++;
   second=0;
   delay(250);
  }


}

So when I get home I'm going to try putting parts of your code into this. But at that point, I need help on how to assign the A0-A5 pins so I can have seconds as well. And also, why is Pin0 an input? What is being inputted? If I can use my 1hz crystal oscillator there that would be great. I have a pretty accurate frequency on it so long as the clock as at room temperature.

I'm not familiar with an 8 bit shift registrar. I see how it can act as both the 10digit and 1digit though. If this chip is meant to be used outside the arduino I would end up needing a few 4 input NAND gates. Unless the arduino can act as that.. I'm sure it can. Oh boy, this is a lot of information to cram in. I gotta crank it out by the end of the week. Afterwards I can take more time to enjoy the possibilities of the arduino though as I finish building my LED cube :smiley:

Ok so I tested my highvoltage supply and the tubes light up great. So if I can get the arduino working (5 volt outputs right?) then I'll have this clock up and running in no time. Gonna be a lot of soldering in my future.

I was trying to use ttl chips like the 74161 but everytime something very random and weird would happen even though everything is wired correctly.

When you wired things up 'correctly' did you remember to include the decoupling capacitor(s) on the VCC pin(s)?

Don

I didn't use bypass capacitors actually. The primary reason for that is because I learned about them online and asked my proffessor about them, but he said you don't learn about that till your 2nd semester sophomore year. And considering everyone has their project, no one is using these bypass capacitors I figure I would be fine without them too. Especially considering my highest frequency is only 1hz and the crystal oscillator I made works beautifully without one.
Not saying I shouldn't use them, I just feel that that isn't quite the problem. Wouldn't hurt to just try putting it in though I guess.
The other thing is, while I say random it isn't random. My 2nd attempt ended up consistantly taking count 7 and loading the 2nd counter as well as count 9. So, 01, 02, 03, 04, 05, 06, 07, 18, 19, 20, 21, ect. I think it is because a way I set up pins A-D. While it works in the simulator I think they should simply be grounded at all times instead. The odd thing is, the 2nd counter counts when it receives a signal into its CLK right? So I tested that and it ONLY gets the signal when it should, at 9. So how it added the extra count into the logic is beyond me. Again could be the A-D not being grounded or not using a bypass cap. I'm working on attempt #3 using logic chips, but would definately prefer using the Arduino

I switch between the two. Trying to get the arduino to work correctly and building attempt #3.
If I can figure out how to get the arduino to work correctly then I can add so many more features like an alarm, or steampunkish features where every hour the arduino spins a motor and turns gears on the enclosure I build, just so many things I can do with the arduino than being restricted to these chips.

This is the website with the code I'm trying to use. Although I guess I have to figure it out myself if I want to use seconds as well. I can't get this one to work anyway, the LED's don't represent the proper counting at all.

I just got some bypass caps to add to the circuit

I got an update. Ignore everything I've said but the 4 bit counting arduino. I rewrote and wrote in new code for my arduino. It's working great now! Problem is, I only have 17 pins to count and I need 19. The last 2 pins are being used for my minute and hour setting buttons.

I can't multiplex this either because of the nixie tubes. Any suggestions on how to get those last 2 pins?
edit: forgot I have 20. Means I need one more pin... Maybe if I make the minute setter set hours if held down for a period of time instead.. unless there is a better way

Reply #5: use 3 8-bit shift registers, each drives two 74141 chips for two tubes.
Frees up lots of pins for other stuff, like buttons for setting the time.

CrossRoads:
Reply #5: use 3 8-bit shift registers, each drives two 74141 chips for two tubes.
Frees up lots of pins for other stuff, like buttons for setting the time.

Alright. I was hoping to avoid them but looks like it is my best option. Especially if I want to use more pins for various other functions like an alarm or enclosure actions.

That or build up a standalone board using a chip with more IO pins, like ATMega164/324/644/1284. Availabe in DIP, programmed the same, 32 IO pins vs 20.