Saturday, September 14, 2019

0000 0000 0000 1100

CD4077 XNOR Gate


For quite a long time the inspiration for buying electronics came primarily from online gurus such as Julian Illett, Big Clive, Great Scott and many others. If those enlightened souls reckoned an AP2112 3.3V regulator was a good thing then I jumped online and ordered a swag of them. It was great a couple of years ago because direct sourced components were cheap (and still remain relatively so compared to local suppliers), but of course I didn't really have the time or the talent to put these components to good use.

Then in 2018 I met young Joseph - a madcap toddler obsessed with repeatedly flicking on and off electrical outlet switches. He wasn't getting much joy from the flicking and it was driving his parents a little batty. I had a bit of think and dug around in the many buckets of components and came up with the idea of using an XNOR gate logic chip based circuit. 

The idea behind the CD4077 is that the state of the output pin ALWAYS changes when one of the input pins changes.


Pick a state, switch X or Y and watch Z change

Four inputs via buttons, and one output that will always change

The XNOR gate wired up with output from pin 3

Breadboarded for testing
Low skill soldering - but robust
So now code some randomness to confound the little tyke.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
// ATMEL ATTINY13a μC
// 
//                                   +-\/-+
//  RESET--ACD0--5/A0--PCINT5--PB5  1|    |8  VCC
//   CLKI--ACD3--3/A3--PCINT3--PB3  2|    |7  PB2--PCINT2--2/A1--SCK--ADC1
//         ACD2--4/A2--PCINT4--PB4  3|    |6  PB1--PCINT1---1---MISO--OCOB--INT0*
//                             GND  4|    |5  PB0--PCINT0---0---MOSI--OCOA*
//                                   +----+
//  * indicates PWM port

#include <avr/interrupt.h>                    // for interrupt routines
#include <avr/sleep.h>                        // the sleep routines

#define InterruptPin PB4                      // A2 interrupt pin
volatile uint16_t lastpins = 0b00000000;      // store last lights so they are not the same
volatile uint16_t whichpins = 0b00001111;     // storage for current lights
volatile uint16_t myrand = 2901;              // happy birthday

// generate a "random" number between small and big
uint16_t gimmerand(uint16_t small, uint16_t big) {
  myrand ^= (myrand << 13);
  myrand ^= (myrand >> 9);
  myrand ^= (myrand << 7);
  return abs(myrand)%23*(big-small)/23+small;
}

// gets a new set of random lights, then displays and stores them
void flickthem() {
  while (lastpins == whichpins) {
  whichpins = gimmerand(1, 15);
  }
  PORTB = whichpins;
  lastpins = whichpins;
  delay(50); 
}

// waits for button input, then grabs the new lights
void waitforswitch(void) {
    sei();                                // enable global interrupts
    set_sleep_mode(SLEEP_MODE_IDLE);      // sleep little one
    sleep_enable();                       // enable sleep mode
    sleep_mode();                         // system sleeps here
    
    sleep_disable();                      // ISR routine returns here so wake up        
    delay(50);                            // settle time

    flickthem();                          // change lights please
  
}

// Interrupt
ISR(PCINT0_vect)
{
  // wake up little one...
}

void setup() {
GIMSK |= (1<<PCIE);                   // activate Pin change interrupts
PCMSK |= (1<<InterruptPin);           // sets the Pin change interrupt mask
DDRB = 0b00000000;                    // make all Pins input
// read three pins and add for randomseed
myrand = analogRead(A0)+analogRead(A1)+analogRead(A2);
DDRB = 0b00001111;                    // set output pins for light
flickthem();                          // alive! all pins on to start with (setup check)
}

void loop() {
  // put your main code here, to run repeatedly:
  waitforswitch();                    // sleep and then wait for a button
}

and finally box the whole thing up and smother in hot glue!







No comments:

Post a Comment