Showing posts with label PICAXE. Show all posts
Showing posts with label PICAXE. Show all posts

Friday, April 5, 2019

7 Segment 4x4 Random Word Display

-----
This is primarily a variant of the "Four Letter Word Clock" that we modified after getting tired of Daylight Savings Time making us push a few buttons twice a year to correct the time.  Actually, the project is more entertaining now.

The "Four Letter Word Clock" project page provides the BOM and schematics.  We left the Real Time Clock (RTC) implementation in the source code below, but it is not needed as a RTC is not used.

We were able to put 1,002 four letter words into the EPROM,  Since we display two four letter words selected at random that is over a million possible combinations.  The PICAXE random number generator is seeded by doing an analog read on an ADC open pin; basically we read 'noise' and use that for the seed.  It's pretty random, but I don't expect the method to be used in Vegas slot machines
-----
It's interesting to see the combinations produced by the rig.  Bored?  Watch this 4 minute demo:

It's a fun build.
-----
The PICAXE source code is:
#rem
 *******************************
 ***** www.WhiskeyTangoHotel.Com  *****
 *******************************   
    Project Name: 4Letter Word Clock

    Start Date: August 2012
   
    Program Rev History:
       March 2019.  Now called "4Letter Word by 4Letter"
     Tired of the simple two time/year DST change
     so we changed to format to display to random 4 letter
     words side by side.  The words are now random and not sequintial.
   

 *******************************

http://www.dealextreme.com/p/8x-digital-tube-8x-key-8x-double-color-led-module-81873

#endrem

;
;LKM1638 Input pin 3 (CLK)      ---> 18M2 c.0 LEG 17
;LKM1638 Input pin 4 (DIO)      ---> 18M2 c.1 LEG 18
;LKM1638 Input pin 5 (STB0)     ---> 18M2 c.2 LEG 1

;24LC156 EERPOM WP (Write Protect) GND
;24LC156 EERPOM SDA          ----> 18M2 b.1 LEG 7
'24LC156 EERPOM SCL           ----> 18M2 b.4 LEG 10

#picaxe 18m2
#no_data    'do not read internal 18M2 EEPROM

dirsc = 010111        ;c0, c1, c2, c4 as output
symbol clock    = c.0    ;Clock output pin
symbol dio        = c.1    ;Data input output pin
symbol strobe    = c.2    ;Strobe output pin

' s1 thru s8 are the tact swithes under the single RED/Green LEDs
symbol s1        = bit16 ;b2        'to set hours
symbol s2        = bit17 ;b2        ' to set minutes - both to set seconds
symbol s3        = bit18 ;b2
symbol s4        = bit19 ;b2
symbol s5        = bit20 ;b2
symbol s6        = bit21 ;b2
symbol s7        = bit22 ;b2
symbol s8        = bit23 ;b2    'toggle to turn on and off the ticker relay

symbol dataio    = b0 ;w0 and bit 0 to bit 7
symbol pad        = b1 ;w0 and bit 8 to bit 15
symbol iobuf    = w0 ;b0, b1
symbol keys        = b2 ;bit16 to bit 23
symbol fixaddr    = b3 ;start address for DE display

symbol Segment4LEFT    = b4  ;Rightmost 7 seg, LEFT Side
symbol Segment4RIGHT     = b5  ;Rightmost 7 seg, RIGHT Side
symbol Segment2LEFT    = b6  ;Leftmiddle 7 seg, LEFT Side
symbol Segment3LEFT    = b7  ;Rightmiddle 7 seg, LEFT Side
symbol Segment2RIGHT    = b8  ;Leftmiddle 7 seg, Right Side
symbol Segment3RIGHT      = b9  ;Rightmiddle 7 seg, Right Side
symbol Segment1LEFT      = b10 ;Leftmost 7 seg, LEFT Side
symbol Segment1RIGHT    = b11 ;Leftmost 7 seg, Right Side

symbol char        = b12
symbol bank        = b13
symbol tmpry     = b14
symbol dispbrit    = b15
symbol autoaddr    = b16
symbol readmode    = b17
symbol tmpry2    = b18
symbol EEPROMChar = b19
'w10 (b20/21) = used to read var from EEPROM
symbol LEDTicker  = b22

symbol seconds = b23 ' vars for RTC
symbol minutes = b24
symbol hours = b25
symbol blinky = b26 'for RTC 010000 would Enable output at 1Hz blink rate.  000000 is no blink
symbol junkread = b27 'used to read/write RTC day, month, year, date.  Also as a temp var in time set adjust routines

fixaddr        = $c0
dispbrit        = $88    '$88 (136DEC)  min bright.   $8F (143DEC) max bright
autoaddr        = $40
readmode         = $42

init:
high strobe            ;Ensure strobe is initially high
gosub clearchars        ;Clear all characters
blinky = 010000 ' 010000 would Enable output at 1Hz blink rate, start w/ relay click ON..  000000 is no blink.

' Set the time on the DS1307 RTC
i2cslave %11010000, i2cslow, i2cbyte    ; set PICAXE as master and DS1307 slave address
pause 50
'\/ \/ \/ \/ Un_REM THESE LINES (BELOW) IF SETTING UP A NEW RTC  \/ \/ \/ \/
#rem
' Set the RTC chip time
;  write time and date e.g. to 11:59:00 on Thurs 25/12/03
'; would be "writei2c 0,($00, $59, $11, $03, $25, $12, $03, 010000)"
' readi2c 0, (b0,b1,b2,b3,b4,b5,b6,b7) reads back the data

let hours = $19        ; 01-12 Note all BCD format
let minutes = $11         ; 00-59 Note all BCD format  
let seconds = $10    ; 00-59 Note all BCD format

; program does not use for we use seconds.  Set manually in the write statement
' for SQ Wave out on RTC.  Last val: 010000 would Enable output at 1Hz blink rate.  000000 is no blink

writei2c 0, (seconds, minutes, hours, 01, 01, 01, 01, blinky)
pause 50

#endrem
'/\ /\ /\ /\ Un_REM THESE LINES (ABOVE) IF SETTING UP A NEW RTC  /\ /\ /\ /\


;--------------------------------------------------------

'I have laid out the 8 segments in the display as:

'| Segment1LEFT | Segment2LEFT | Segment3LEFT | Segment4LEFT | Segment1RIGHT | Segment2RIGHT | Segment3RIGHT | Segment4RIGHT

    ;Segment Values                0-9   = ( 0 , 1,  2 , 3 , 4 , 5 , 6 , 7, 8 , 9,
    '                              10-19 =   A , b , C , d , E , F , g,  H, i,  J,
    '                              20-29 =   K,  L,  M,  N,  o,  P,  q,  r, S,  T, 
    '                              30-35 =   U, V, W,  X,  y,   Z ,
    '                              36-44 =   segA, segB, segC, segD, segE, segF, segG, dp, off)

'the 'gosub display' routine expect 8 values; SegmentxLEFT and SEGMENTxRIGHT coded as
'lookup values shown in the rem above.

' At Startup turn the clicky relay on.  S8 button will turn it off
blinky = 010000
i2cslave %11010000, i2cslow, i2cbyte
writei2c 0, (seconds, minutes, hours, 01, 01, 01, 01, blinky)

main:

if s1 = 1 or s2 = 1 or s8 = 1 then 'setting the clock time or relay ticker
    if s1 = 1 and s2 = 0 then 'setting hours
        junkread = junkread + 1
        if junkread > 23 then
            junkread = 0
        end if
        lookup junkread, ($00,$01,$02,$03,$04,$05,$06,$07,$08,$09,$10,$11,$12,$13,$14,$15,$16,$17,$18,$19,$20,$21,$22,$23), hours
         i2cslave %11010000, i2cslow, i2cbyte
        writei2c 0, (seconds, minutes, hours, 01, 01, 01, 01, blinky)
        pause 10
    endif ' s1 = 1, setting hours
   
    if s2 = 1 and s1 = 0 then 'setting minutes
        junkread = junkread + 1
        if junkread > 59 then
            junkread = 0
        end if
        lookup junkread, ($00,$01,$02,$03,$04,$05,$06,$07,$08,$09,$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), minutes
         i2cslave %11010000, i2cslow, i2cbyte
        writei2c 0, (seconds, minutes, hours, 01, 01, 01, 01, blinky)
        pause 10
    endif 's2 = 1, setting minute
   
    if s1 = 1 and s2 = 1 then 'reset seconds to 00
        seconds = $00
        i2cslave %11010000, i2cslow, i2cbyte
        writei2c 0, (seconds, minutes, hours, 01, 01, 01, 01, blinky)
        pause 10
    endif 'settin seconds to zero

    if s8 = 1 then ' turn on/off the clicking relay
        'read the RTC to dected the seconds for the write to RTC below keeps them accurate
        i2cslave %11010000, i2cslow, i2cbyte    ; set PICAXE as master and DS1307 slave address
        readi2c 0,(seconds, minutes, hours, junkread, junkread, junkread, junkread, blinky)
        pause 10
        if blinky = 010000 then 'blinky from RTC is ON and clinking the relay. turn it OFF
            blinky = 000000
        else              'blinky from RTC is OFF and NOT clinking the relay. turn it ON
            blinky = 010000
        end if
        i2cslave %11010000, i2cslow, i2cbyte
        writei2c 0, (seconds, minutes, hours, 01, 01, 01, 01, blinky)
        pause 500
    end if
   

else ' not settign the clock, check for brightness adjust and run as normal; so read a new 4letter word
   
    if s7 = 1 then 'increase brightness
        dispbrit = 140 'other values cause random LED7 behavior
    end if

    if s6 = 1 then 'decrease brightness
        dispbrit = 136   ' 136 is min bright
    end if   

sertxd (#dispbrit, 13,10)
   
    'Get SegmentxLEFT values for clock by reading the RTC
    i2cslave %11010000, i2cslow, i2cbyte    ; set PICAXE as master and DS1307 slave address
    readi2c 0,(seconds, minutes, hours, junkread, junkread, junkread, junkread, blinky)
    pause 10
    gosub ReadEEPROM  ' read the four letter word.  These are loaded into SegmentxRIGHT vars
    gosub Ticker    'ticks thru the R/G LEDs to show seconds
endif

' THIS IS WHERE SEGMENT LEFT IS LOADED WITH THE TIME.
' CHANGE IT TO A WORD
'
'Segment1LEFT = hours & %11110000 / 16  'BCD so shift upper 4 bits to lower 4 bits
'Segment2LEFT = hours & 001111

'Segment3LEFT = minutes & %11110000 / 16   'BCD so shift upper 4 bits to lower 4 bits
'Segment4LEFT = minutes & 001111

gosub display   'Put the SegmentxLEFT and SEGMENTxRIGHT characters onto the 7 seg displays.

gosub getkeys        ;Read tact buttons
           
goto main

'-------------------------------------------------------
Ticker: 'ticks thru the R/G LEDs to show seconds by cycling through each LED address

junkread = seconds & %11110000
junkread = junkread / 16 * 10
seconds = seconds & 001111
seconds = junkread + seconds

lookup seconds, (1,1,1,1,1,1,1,1,3,3,3,3,3,3,3,3,5,5,5,5,5,5,5,5,7,7,7,7,7,7,7,7,9,9,9,9,9,9,9,9,11,11,11,11,11,11,11,11,13,13,13,13,13,13,13,13,15,15,15,15), dataio

dataio = dataio + fixaddr    ;LEDs are at odd addresses 1 to 15
junkread = dataio   'used to turn off LED later in this sub
low strobe
gosub sendchar

LEDTicker = LEDTicker + 1

if LEDTicker = 2 then
    LEDTicker = 1
end if

dataio = LEDTicker  'Light the LEDs.  1 = RED.  2 = GREEN.  3 = R/G
gosub sendchar
high strobe

'Turn off LED here
dataio = junkread   
low strobe
gosub sendchar
dataio = 0   '0 turns off the currently selected LED
gosub sendchar
high strobe;

dataio    = dispbrit        ;Display control on, brightness level
low strobe                 ;Strobe low
gosub sendchar
high strobe                ;Strobe high

return 'Ticker

ReadEEPROM:
'24LC256 EEPROM is loaded with 987 four letters words (3948 characters)
'Each character is an address from 0 to 3947
'readi2c addrs, (charvalue)

i2cslave %10100000, i2cslow, i2cword    ; set PICAXE as master and DS1307 slave address

'Read and Translate the char read from the EEPROM for the lookup(.,...), dataio command.
'Read the EEPROM letter then subtract 87 from that ASCII value for the "lookupchar" sub.  Examples:
'ASCII value for a = 97; Lookup in this program value is 10.  So, 97 - 87 = 10
'ASCII value for j = 106; Lookup in this program value is 19.  So, 106 - 87 = 19
'ASCII value for k = 122; Lookup in this program value is 35.  So, 122 - 87 = 35

'Last word in EEPROM is YURT and starts at Location 4008

touch16 B.7, b20 'lower bits w10
touch16 B.7, b21 'w10 upper
'RANDOM number for w10
w12 = w10 // 1003  ; scale it to 0-1002 (4 * 4008 = 4008)
w10 = w12 * 4  ; max is YURT at 4008 start

readi2c w10, (Segment1LEFT)
Segment1LEFT = Segment1LEFT - 87

w10 = w10 + 1
readi2c w10, (Segment2LEFT)
Segment2LEFT = Segment2LEFT - 87

w10 = w10 + 1
readi2c w10, (Segment3LEFT)
Segment3LEFT = Segment3LEFT - 87

w10 = w10 + 1
readi2c w10, (Segment4LEFT)
Segment4LEFT = Segment4LEFT - 87
'
'
'
touch16 B.7, b20 'lower bits w10
touch16 B.7, b21 'w10 upper
'RANDOM number for w10  
w12 = w10 // 1003  ; scale it to 0-1002 (4 * 4008 = 4008)
w10 = w12 * 4  ; max is YURT at 4008 start

readi2c w10, (Segment1RIGHT)
Segment1RIGHT = Segment1RIGHT - 87

w10 = w10 + 1
readi2c w10, (Segment2RIGHT)
Segment2RIGHT = Segment2RIGHT - 87

w10 = w10 + 1
readi2c w10, (Segment3RIGHT)
Segment3RIGHT = Segment3RIGHT - 87

w10 = w10 + 1
readi2c w10, (Segment4RIGHT)
Segment4RIGHT = Segment4RIGHT - 87

pause 1500 'keep the secs LED on and slow down the words

return ' ReadEEPROM


;--------------------------------------------------------

display:    ;Displays data on the 7 seg displays, using 2 blocks of 4 digits

    bank = 0   ;LEFT Side: First block of digits

    dataio    = fixaddr + bank + 0 ;Set Leftmost 7 seg, LEFT Side write address
    low strobe                 ;Strobe low
    gosub sendchar
    char = Segment1LEFT        ;Leftmost 7 seg, LEFT Side
    gosub lookupchar
    gosub sendchar
    high strobe                ;End of data - Strobe high
   
    dataio    = fixaddr + bank + 2 ;Set Leftmiddle 7 seg, LEFT Side write address
    low strobe                 ;Strobe low
    gosub sendchar
    char = Segment2LEFT        ;Leftmiddle 7 seg, LEFT Side
    gosub lookupchar
    gosub sendchar
    high strobe                ; End of data - Strobe high
   
    dataio    = fixaddr + bank + 4 ;Set Rightmiddle 7 seg, LEFT Side write address
    low strobe             ; Strobe low
    gosub sendchar
    char = Segment3LEFT    ;Rightmiddle 7 seg, LEFT Side
    gosub lookupchar
    gosub sendchar
    high strobe            ;End of data - Strobe high
   
    dataio    = fixaddr + bank + 6 ;Set Rightmost 7 seg, LEFT Side write address
    low strobe             ; Strobe low
    gosub sendchar
    char = Segment4LEFT    ;Rightmost 7 seg, LEFT Side
    gosub lookupchar
    gosub sendchar
    high strobe            ;End of data - Strobe high
   
    'RIGHT BANK
    bank = 8  ;RIGHT Side: Second block of 4 digits
    dataio    = fixaddr + bank + 0 ;Set Leftmost 7 seg, Right Side write address
    low strobe             ;Strobe low
    gosub sendchar
    char = Segment1RIGHT    ;Leftmost 7 seg, Right Side
    gosub lookupchar
    gosub sendchar
    high strobe            ;End of data - Strobe high
   
    dataio    = fixaddr + bank + 2 ;Set Leftmiddle 7 seg, Right Side write address
    low strobe             ;Strobe low
    gosub sendchar
    char = Segment2RIGHT    ;Leftmiddle 7 seg, Right Side
    gosub lookupchar
    gosub sendchar
    high strobe            ;End of data - Strobe high
   
    dataio    = fixaddr + bank + 4 ;Set Rightmiddle 7 seg, Right Side write address
    low strobe             ; Strobe low
    gosub sendchar
    char = Segment3RIGHT    ;Rightmiddle 7 seg, Right Side
    gosub lookupchar
    gosub sendchar
    high strobe            ; End of data - Strobe high
   
    dataio    = fixaddr + bank + 6 ;Set Rightmost 7 seg, RIGHT Side write address
    low strobe             ; Strobe low
    gosub sendchar
    char = Segment4RIGHT    ;Rightmost 7 seg, RIGHT Side
    gosub lookupchar
    gosub sendchar   
   
    '-----------------
   
    'must refresh dispbrit each time
    dataio    = dispbrit ;Display brightness level. $88 (136DEC)  min bright.   $8F (143DEC) max bright
    low strobe         ; Strobe low
    gosub sendchar
    high strobe        ; Strobe high

return   'display

;--------------------------------------------------------

clearchars:            ;Clear LEDs and 7 seg displays.  ALL LEDS OFF. Segs and LEDs
    dataio    = autoaddr ; Data mode auto increment
    low strobe         ; Strobe low
    gosub sendchar
    high strobe        ; Strobe high
    ;
    low strobe         ; Strobe low
    dataio    = fixaddr ; Set start address
    gosub sendchar
    for tmpry = 1 to $0f    ;$0F = 15, so loop runs 16 times.  7 LEDs and 7 seg displays
        dataio = 0        ;Zero blanks the  display
        gosub sendchar
    next
    high strobe            ;Strobe high, keep low to end of data
return

;--------------------------------------------------------

sendchar:    ;Routine to send all characters to LKM1638 module serially
    pad        = $ff    ;$FF = 255.  Set counter
    high clock        ;Ensure clock is high for pulseout
    do
      pinc.1 = bit0    ;Make c.1 the value in bit0
      iobuf = iobuf/2    ;Shift right
      pulsout clock,1 '10us clock pulse
    loop Until pad = 0  'excecute 256 times
return

;--------------------------------------------------------

getkeys:    ;Reads the input tact buttons in and places them in bits16 to bits23
dataio    = readmode    ; Data mode read
low strobe
gosub sendchar
input c.1            ;set c.1 as input
high clock            ;Ensure clock is high for pulseout
for tmpry = 1 to 16    ;Read in bits 0-15
    bit0 = pinc.1    ;Make bit0 the value on c.1. Need to use c.1 as it is both in & out
    iobuf = iobuf*2    ;Shift bit left
    pulsout clock,1    ;10us clock pulse, read next bit
next
s6 = bit3            ;Move 1st word switch values out of buffer
s2 = bit7
s5 = bit11
s1 = bit15
for tmpry = 1 to 16    ;Read in bits 16-31
    bit0 = pinc.1    ;Make bit0 the value on b.0. Need to use c.1 as it is both in & out
    iobuf = iobuf*2    ;Shift bit left
    pulsout clock,1    ;10us clock pulse, read next bit
next
s8 = bit3            ;Move 2nd word switch values out of buffer
s4 = bit7
s7 = bit11
s3 = bit15   
output c.1            ;Return c.1 to output
high strobe
return

;--------------------------------------------------------

lookupchar:    ;Looks up the code to display the digit in 'char' on the 7 seg display
    ;character  0-9   =    ( 0 , 1,  2 , 3 , 4 , 5 , 6 , 7, 8 , 9,
    '               10-19 =         A , b , C , d , E ,  F , g,  H, i,   J,
    '               20-29 =         K,  L,  M,  N, o,   P,  q,  r,  S,  T, 
    '               30-35 =         U, V, W,  X,  y,   Z ,
    '               36-44 =        segA, segB, segC, segD, segE, segF, segG, dp, off)

    lookup char,(63,6,91,79,102,109,125,7,127,111,119,124,57,94,121,113,111,118,16,30,118,56,21,84,92,115,103,80,109,120,62,28,42,118,110,91,1,2,4,8,16,32,64,128,0),dataio

return

;------------------------

Tuesday, August 6, 2013

Failure Tutorial: All hail the Mighty Bypass Cap

It's frustrating.  You design a great project, get it working perfectly on the breadboard with that nice beefy bench power supply only to discover it stops working in "the real world".  What the hell's going on?
-----

Here is a short video showing how everything just stops when the bypass cap from my Etch-a-Sketch to chart Temperature vs Time is removed.  Connect the bypass cap and, like magic, everything is back to normal.  Pretty amazing, huh?
-----
If you follow DIY projects on the web you see this issue frequently.  The fix often is simply to add a capacitor between power and ground.  This is called a by-pass cap or decoupling cap.  They are most useful in projects with electrical noise or where larger loads like motors, solenoids, relays, etc. are involved.

As I said, this recently happened to me.  I had the great idea to use two stepper motors mounted to an Etch-a-Sketch to chart Temperature vs Time.  The project came off fine in the end, but not without a bump in the road.

The rig was stable with one stepper motor.  However, adding the second stepper motor made everything 'wacky'.   Sometimes the PICAXE 18M2 microcontroller would not even accept new code downloads.  All fixed with a by-pass cap.
-----
Below is short video of the finished rig in action. (Thanks Hack-a-Day for featuring it!)  Take a look at the build page if you are interested in duplicating the project.

-----
Thanks for the visit and "All hail the mighty bypass cap"!!!

Thursday, April 11, 2013

Hand of PI (Twitter controlled Robot Hand)

OBJECTIVE:  Use the Raspberry PI to monitor a Twitter feed and control a mechanical device.

If you are not interested in the details of the build and just want to see the result you can watch the vid below.  

-----
RESULT:  Success!!!  You can control the "The Hand of PI" by sending a tweet to @OurCatDoor.   If  your tweet includes any of the text below, the "Hand of PI" obeys your command.  Valid commands are (lowercase):
  • one (holds up one finger)
  • peace (shows the two finger peace sign)
  • three (three fingers up)
  • hookem (if you are a Texas Longhorn fan this one makes sense)
  • fist (the Hand of PI gets ready to fight)
  • open (ready for a 'high five')
  • finger (well...  this will be the most tweeted command)
Go ahead, try it!!!  Send a tweet command to @OurCatDoor to let us know you were here.
-----
Basically what you are seeing is the Raspberry PI running a Python script searching any tweet sent to @OurCatDoor.  In the video, an iPad sends a tweet to @OurCatDoor that has the command "finger" in it.  It takes a few seconds, but the Raspberry PI finds the tweet, parses it, and find the "finger" command.  The Python script then sets the PI's GPIO ports High/Low.  The PI GPIO is connected to a PICAXE 18M2 (via a HC7404 buffer).  The PICAXE 18M2 reads the PI's GPIO to control five servo motors.  "Hand of PI" reacts with the appropriate gesture.  Watch closely and you can see the text on the screen update as the "finger" command is found and the "Hand of PI" gestures.   There's a lot going on here.  Confused?  This diagram should help (click to see full size):
Of course this isn't full schematic, but it lays out all the I/O to align with the source code you see below.  Really, the interconnects and 5VDC to the servos, PI, PICAXE, and HC7404 is something anyone wanting to duplicate the project should easily understand given the block diagram and source code.
-----
Let's show a few more pics and action videos of the rig before we get into the source code:
 
-----
This video is a bit long but demonstrates all the gestures of the "Hand of PI".  The screen in the background shows output from the Python script.  The screen is not needed, but I included it in the video to show the tweets as they are captured.  Note the "Hand of PI" reacts when a new tweet command is found.
Everyone wants to see the "Hand of PI" flip the bird; that is the last gesture if you want to skip to the end...
----
If you are still with us, enjoy some source code for your reading pleasure.

First the program that is running on the PICAXE 18M2.  It's job is to read the Raspberry PI's GPIO output and control the five servo motors on the "Hand of PI".

' PICAXE 18M2 for RaspPI intergration to Tweeter Controlled Hand Gesture Robot APRIL 2013
'"THE HAND OF PI"
' www.whiskeytangohotel.com
' NOTE: PICAXE Program Editor Rev newer than 5.3.6 causes servo jitter***
' Other than the minium PICAXE 18M2 'keep alive' 22K R & 10K R
' no other R, C, L, etc need for the project.
' Everything on PICAXE powered by 4.5VDC
' The PICAXE drives the servos straight from the chip.
' See pinouts in comments

' 0 is Thumb (PICAXE pin 6)
' 1 is Pointer (PICAXE pin 7)
' 2 is Middle (PICAXE pin 8)
' 3 is Ring (PICAXE pin 9)
' 4 is Pink (PICAXE pin 10)
' Normally Open Button Switch is PICAXE pin 18 (pulled HIGH with 10K)
; this button will not be used for the PI intergration

' PI GPIO 11 connected to c.0 (PICAXE pin 17)
' PI GPIO 13 connected to c.7 (PICAXE pin 16)
' PI GPIO 15 connected to c.6 (PICAXE pin 15)

symbol RaspPI11 = pinc.0
symbol RaspPI13 = pinc.7
symbol RaspPI15 = pinc.6

'Define Servo values to fully EXtend/Open finger
Symbol Ex_Thumb = 60
Symbol Ex_Pointer = 60
Symbol Ex_Middle = 245
Symbol Ex_Ring = 60
Symbol Ex_Pink = 60

'Define Servo values to fully CLose finger
Symbol CL_Thumb = 225
Symbol CL_Pointer = 240
Symbol CL_Middle = 50
Symbol CL_Ring = 240
Symbol CL_Pink = 240

'Init the servos
servo 0, Ex_Thumb
servo 1, Ex_Pointer
servo 2, Ex_Middle
servo 3, Ex_Ring
servo 4, Ex_Pink

pause 400

'Gesture Subroutines are (2^3 = 8 can be PI Callable)
' Valid Tweet commands are: one, peace, three, hookem, fist, finger, wave

'Insure Open_Hand position at program start
gosub Open_Hand
pause 500

main:  'This loops until hell freezes over

'Read the RasPI GPIO bus and  jump to gesture sub routine

If RaspPI15 = 0 and RaspPI13 = 0 and RaspPI11 = 0 then
gosub Open_Hand
end if

If RaspPI15 = 0 and RaspPI13 = 0 and RaspPI11 = 1 then
gosub One
end if

If RaspPI15 = 0 and RaspPI13 = 1 and RaspPI11 = 0 then
gosub Peace
end if

If RaspPI15 = 0 and RaspPI13 = 1 and RaspPI11 = 1 then
gosub Three
end if

If RaspPI15 = 1 and RaspPI13 = 0 and RaspPI11 = 0 then
gosub Hook_em
end if

If RaspPI15 = 1 and RaspPI13 = 0 and RaspPI11 = 1 then
gosub Fist
end if

If RaspPI15 = 1 and RaspPI13 = 1 and RaspPI11 = 0 then
gosub F_You
end if

'If RaspPI15 = 1 and RaspPI13 = 1 and RaspPI11 = 1 then
' gosub Wave  'wave is pretty hard on the servos, so we commented it
'end if

pause 5
goto main

' Gesture Subroutines below:
Open_Hand:
servopos 0, Ex_Thumb
servopos 1, Ex_Pointer
servopos 2, Ex_Middle
servopos 3, Ex_Ring
servopos 4, Ex_Pink
return ' Open_Hand

Hook_em:
servopos 0, CL_Thumb
servopos 1, Ex_Pointer
servopos 2, CL_Middle
servopos 3, CL_Ring
servopos 4, Ex_Pink
return 'Hook_em

F_you:
servopos 0, CL_Thumb
servopos 1, CL_Pointer
servopos 2, Ex_Middle
servopos 3, CL_Ring
servopos 4, CL_Pink
return 'F_you

One:
servopos 0, CL_Thumb
servopos 1, Ex_Pointer
servopos 2, CL_Middle
servopos 3, CL_Ring
servopos 4, CL_Pink
return 'One

Peace:
servopos 0, CL_Thumb
servopos 1, Ex_Pointer
servopos 2, Ex_Middle
servopos 3, CL_Ring
servopos 4, CL_Pink
return 'Two

Three:
servopos 0, CL_Thumb
servopos 1, Ex_Pointer
servopos 2, Ex_Middle
servopos 3, Ex_Ring
servopos 4, CL_Pink
return 'Three

Four:
servopos 0, CL_Thumb
servopos 1, Ex_Pointer
servopos 2, Ex_Middle
servopos 3, Ex_Ring
servopos 4, Ex_Pink
return 'Four

Fist:
servopos 0, CL_Thumb
servopos 1, CL_Pointer
servopos 2, CL_Middle
servopos 3, CL_Ring
servopos 4, CL_Pink
return 'Fist

Wave:  'waves the fingers
servopos 0, CL_Thumb
pause 70
servopos 1, CL_Pointer
pause 70
servopos 2, CL_Middle
pause 70
servopos 3, CL_Ring
pause 70
servopos 4, CL_Pink
pause 70

servopos 0, Ex_Thumb
pause 70
servopos 1, Ex_Pointer
pause 70
servopos 2, Ex_Middle
pause 70
servopos 3, Ex_Ring
pause 70
servopos 4, Ex_Pink
return 'Wave
----
Now for the Python script running on the Raspberry PI.  It's job is to search any tweet sent to @OurCatDoor and parse it for a "Hand of PI" command, then set the PI's GPIO for input to the PICAXE 18M2.



# WhiskeyTangoHotel.com - APRIL 2013   (special thanks to @Rob_Bishop)
# Error traps entered due to json hitting web site that was down etc.
# For next added to end of prog to blink LED to show program is running.

# Import the urllib library to read data from webpages
import urllib

# Import the simplejson library to  decode the data read from the webpage
import simplejson

# Import the time library for delay and lepse time tracking
import time
CurrentTime = time.time()

# Import the Raspberry Pi GPIO libraries
import RPi.GPIO as GPIO

# Set-up the GPIO pins
# Clear the current set-up
GPIO.cleanup()

# Set up the GPIO library to use Raspberry Pi board pin numbers
GPIO.setmode(GPIO.BOARD)

# Set pin 11, 13, 15  on the GPIO header to be an output
GPIO.setup(11,GPIO.OUT)  #PIXACE leg 17 (c.0)
GPIO.setup(13,GPIO.OUT)  #PIXACE leg 16 (c.7)
GPIO.setup(15,GPIO.OUT)  #PICAXE leg 15 (c.6)
GPIO.setup(7,GPIO.OUT)   #Blinkie LED to let us know the prog is running

# Start with Open Hand
GPIO.output(11,GPIO.LOW)
GPIO.output(13,GPIO.LOW)
GPIO.output(15,GPIO.LOW)
Last_gesture = "open"
Error_hit = 0
print "Hand open.  Waiting for Tweet...","\n"

# Function to take Twitter handle (e.g. @Raspberry_Pi) as an argument and return the most recent tweet

# Define the function name and show the arguments
def Latest_Tweet_to_Twitter_Handle(twitter_handle):
try:
# Get the results of a search on Twitter for tweets containing the given hand$
Twitter_search_results = urllib.urlopen("http://search.twitter.com/search.json?q="+twitter_handle)

# Decode the data that we got from the webpage to form a list of tweets
result_list = simplejson.loads(Twitter_search_results.read())

# The function returns the first result in the list
return result_list["results"][0]["text"]
except:
pass

# Main body of the program - Get the latest tweet and check if it contains certain words
# Loop to run forever

#Twitter commands the hand understands are:
#one, two, three, hookem, fist, finger, wave

while(True):
try:
#Time since program start in seconds
DeltaTime = int(time.time() - CurrentTime)

# Function gets the latest tweet mentioning the handle given in next line
Tweet=Latest_Tweet_to_Twitter_Handle("@OurCatDoor")

# START TEST(open): Check if tweet contains the word given in quotation marks
if "open" in Tweet: # and Last_gesture != "open":
Last_gesture = "open"
# If it did contain the word then print out the tweet along with a message
print DeltaTime,"seconds:",Tweet," - Gesture OPEN HAND","\n"
# Turn on the LED
GPIO.output(11,GPIO.LOW)
GPIO.output(13,GPIO.LOW)
GPIO.output(15,GPIO.LOW)
#---END TEST(open)---

# START TEST(one): Check if tweet contains the word given in quotation marks
if "one" in Tweet: # and Last_gesture != "one":
Last_gesture = "one"
# If it did contain the word then print out the tweet along with a message
print DeltaTime,"seconds:",Tweet," - Gesture ONE","\n"
# Set the PICAXE inputs
GPIO.output(11,GPIO.HIGH)
GPIO.output(13,GPIO.LOW)
GPIO.output(15,GPIO.LOW)
#---END TEST(one)---

# START TEST(peace): Check if tweet contains the word given in quotation marks
if "peace" in Tweet: # and Last_gesture != "peace":
Last_gesture = "peace"
# If it did contain the word then print out the tweet along with a message
print DeltaTime,"seconds:",Tweet," - Gesture PEACE","\n"
# Set the PICAXE inputs
GPIO.output(11,GPIO.LOW)
GPIO.output(13,GPIO.HIGH)
GPIO.output(15,GPIO.LOW)
#---END TEST(peace)---

# START TEST(three): Check if tweet contains the word given in quotation mar$
if "three" in Tweet: # and Last_gesture != "three":
Last_gesture = "three"
# If it did contain the word then print out the tweet along with a message
print DeltaTime,"seconds:",Tweet," - Gesture THREE","\n"
# Set the PICAXE inputs
GPIO.output(11,GPIO.HIGH)
GPIO.output(13,GPIO.HIGH)  
GPIO.output(15,GPIO.LOW)
#---END TEST(three)---

# START TEST(hookem): Check if tweet contains the word given in quotation mar$
if "hookem" in Tweet: # and Last_gesture != "hookem":
Last_gesture = "hookem"
# If it did contain the word then print out the tweet along with a message
print DeltaTime,"seconds:",Tweet," - Gesture HOOK EM HORNS","\n"
# Set the PICAXE inputs
GPIO.output(11,GPIO.LOW)
GPIO.output(13,GPIO.LOW)
GPIO.output(15,GPIO.HIGH)
#---END TEST(hookem)---

# START TEST(fist): Check if tweet contains the word given in quotation mar$
if "fist" in Tweet: # and Last_gesture != "fist":
Last_gesture = "fist"
# If it did contain the word then print out the tweet along with a message
print DeltaTime,"seconds:",Tweet," - Gesture FIST","\n"
# Set the PICAXE inputs
GPIO.output(11,GPIO.HIGH)
GPIO.output(13,GPIO.LOW)
GPIO.output(15,GPIO.HIGH)
#---END TEST(fist)---

# START TEST(finger): Check if tweet contains the word given in quotation mar$
if "finger" in Tweet: # and Last_gesture != "finger":
Last_gesture = "finger"
# If it did contain the word then print out the tweet along with a message
print DeltaTime,"seconds:",Tweet," - Gesture FINGER F_YOU","\n"
# TSet the PICAXE inputs
GPIO.output(11,GPIO.LOW)
GPIO.output(13,GPIO.HIGH)
GPIO.output(15,GPIO.HIGH)
#---END TEST(finger)---

# START TEST(wavewave): Check if tweet contains the word given in quotation mar$
if "wavewave" in Tweet: # and Last_gesture != "wave":
Last_gesture = "wavewave"
# If it did contain the word then print out the tweet along with a message
print DeltaTime,"seconds:",Tweet," - Gesture WAVE","\n"
# Set the PICAXE inputs
GPIO.output(11,GPIO.HIGH)
GPIO.output(13,GPIO.HIGH)
GPIO.output(15,GPIO.HIGH)
#---END TEST(wavewave)---

for x in range(0, 10):
# Wait for xx seconds before repeating
# Blinkie LED to let us know the program is running
GPIO.output(7,GPIO.HIGH)
time.sleep(.1)
GPIO.output(7,GPIO.LOW)
time.sleep(1)
except:
pass


-----
If you are still awake, thanks for checking out the build.  Send a tweet to @OurCatDoor to let us know you were here.
-----

Sunday, November 18, 2012

Analog Clock turned DC Voltmeter

Why create, what could be, the most impractical way to measure a DC voltage?  Well, because "Measurement Matters".

Actually, the idea was given to me in the comment section of my Voltmeter Clock project which was featured by the awesome team at "Hack A Day".  That is where rue_mohr wrote the comment, "who can be the first to turn a clock into a volt meter?"  Well, that is (and remains) the stupidest ideal I ever heard.  Now, read on....
----
The concept is easy.  Use the "time" on an analog clock to display measured voltage values between 0-12VDC.  1 o'clock means 1VDC, 2 o'clock means 2VDC; if the time reads 10:30 that means 10.5VDC, etc.   To do this a stepper motor is connected to the adjustment knob of the analog clock.  This short video of the rig being tested should help make things clear:
---
One of the ADC inputs on a PICAXE 18M2 microcontroller is used to read/digitize the voltage to be measured.  After the PICAXE measures the voltage, it gets translated into the number of steps the stepper motor needs to move.  This stepper motor movement adjusts the clock to display the voltage that was measured.  The PICAXE doesn't have enough output current to directly drive a stepper motor so the PICAXE feeds a L293D Motor Driver IC.  The outputs of the L293D are then used drive the stepper motor.

Since the clock can display a maximum value of "12 o'clock", the rig was designed to measure a maximum 12VDC input signal.  However, the max input voltage for the ADC on the PICAXE 18M2 is about 5VDC.  To tame the input signal for the PICAXE a simple 3:1 voltage divider (10K, 10K, 10K) was implemented.  This limited the input voltage into the PICAXE to 4VDC.  A trim pot was also used to adjust for the input impedance of the PICAXE and to help calibrate the measurement results.
----
Here is a video of the rig in action side by side with a DVM.
---
All in all the rig works as designed but has terrible lag and is no way what anybody would consider NIST traceable.  The accuracy is estimated at ~100mV.  The two control buttons pictured below help by allowing manual calibration of the rig to 0VDC (12 o'clock position).
---
I can't imagine that this project will ever be duplicated, but as always I will send schematics and source code to those that request it.  If you're still with us, thanks for checking out our site.
-----
Link back: Hack A Day
Link back: Hacked Gadgets
-----

Wednesday, August 29, 2012

Four Letter Word Clock via uC

Why build a clock that displays four letter words?  The current time is everywhere; on your PC, smartphone, GPS, MP3 player, etc.  Heck, you may even own a watch!  Four letter words are pretty common as well.
-----
So why then?
     1st)  I had this display that I bought from DealExtreme.Com.  The only reason I got it was because it was so cheap.

     2nd) I wanted to experiment with writing/reading data from an EEPROM with a microcontroller.

     3rd) I wanted to experiment with controlling two devices on the I2C bus in one application.

But.... I wanted a fun project idea to make the effort seem somewhat worthwhile and settled on a Four Letter Word Clock.

If you you just want to see the results and are not interested in the build details, here is a short video demo.

The time is shown in 24 hour format on the left four 7-segments.  Every second a different four letter word is shown on the right four 7-segments.  The eight LEDs under the 7-segments progress from left to right as a way to display seconds.  If you listen closely to the video and you can hear a relay that gives the clock a mechanical ticking sound. 

 The buttons under the LEDs are used to set hours (S1), minutes (S2), increase display brightness (S6), decrease display brightness (S7), and turn ON/OFF the mechanical ticking sound (S8) from the relay.

The major components of the build are (full schematic to follow):
     - Eight x 7-Segment + 8 x Red/Green LED + 8 x Input Button Display Module
     - 24LC256 EEPROM to store the 1,003 four letter words
     - DS1307 Real Time Clock (RTC) for time keeping
     - Small relay to provide a clock like, mechanical ticking sound
     - PICAXE 18M2 microcontroller with custom code provides the brains
------

The display from DealExtreme.Com is pretty awesome for the price.  It contains eight 7-segment LED displays, eight LEDs that can be red, green, or red/green, and eight button switches.  The display has a solid, well built feel to it and was a bargain at $4.99.  As a plus, you can control all these feature with only three I/O pins on a microcontroller.  On the downside, it ships with no documentation (zero, zip, nada...) so plan on doing some web searching to understand it.
-----

The 24LC256 EEPROM, DS1307 RTC, and PICAXE 18M2 are easy to get from many web sources.  I rescued the Teladyne 712-5 relay from a trash bound PCB.  A good thing because a web search shows that relay at $28 (it's an RF spec relay!).  No fear, you can leave the relay off or just use any cheap relay as it is not used to switch any current, just for the ticking sound.
-----
Now came the time to load the 24LC256 EEPROM with four letter words.  So... to the internet for a quickie download of all the four letter English words (including all your favorite cuss words) in one tight ASCII text file.  Unfortunately, 7-segment displays don't display letters like "K", "M", "V", "W", "X", and "Z" very readable.  I wrote a short Python script to pull out the offenders, which also meant some of the more 'expressive' words where lost.  After it was all done, there were 1,003 four letters words that easily fit into the 24LC256 EEPROM.  A short (and separate) program was written to tell the PICAXE 18M2 to load these words into the 24LC256 EEPROM.
-----
The harder part was the code to drive the display.  The lack of documentation made it pretty challenging.  I always find the PICAXE forum helpful in these situations (special thanks to "mjy58").  After much coding/debugging, the problem was solved. 

Controlling the two I2C devices (the 24LC256 EEPROM and the DS1307 RTC) from the PICAXE 18M2 was a bit easier than I expected after sorting through the addressing procedures.
----
Here is a short vid (time lapse) of the rig working on the AXE091 development board.  In the vid you can see the eight red LEDs progress from left to right as the seconds tick by.


-----
After verifying the operation for a few days the whole mess was moved off the AXE091 development board and onto a strip board PCB.  Installing the rig into a $3.49 metal project box from Radio Shack provided a clean finished product.
 -----
Below is the build schematic (click to enlarge).  
-----
PICAXE source code:
#rem
 *******************************
 ***** www.WhiskeyTangoHotel.Com  *****
 *******************************   
    Project Name: 4Letter Word Clock

    Start Date: August 2012
   
    Program Rev History:


 *******************************

http://www.dealextreme.com/p/8x-digital-tube-8x-key-8x-double-color-led-module-81873

#endrem

;
;LKM1638 Input pin 3 (CLK)      ---> 18M2 c.0 LEG 17
;LKM1638 Input pin 4 (DIO)      ---> 18M2 c.1 LEG 18
;LKM1638 Input pin 5 (STB0)     ---> 18M2 c.2 LEG 1

;24LC156 EERPOM WP (Write Protect) GND
;24LC156 EERPOM SDA          ----> 18M2 b.1 LEG 7
'24LC156 EERPOM SCL           ----> 18M2 b.4 LEG 10

#picaxe 18m2
#no_data    'do not read internal 18M2 EEPROM

dirsc = 010111        ;c0, c1, c2, c4 as output
symbol clock    = c.0    ;Clock output pin
symbol dio        = c.1    ;Data input output pin
symbol strobe    = c.2    ;Strobe output pin

' s1 thru s8 are the tact swithes under the single RED/Green LEDs
symbol s1        = bit16 ;b2        'to set hours
symbol s2        = bit17 ;b2        ' to set minutes - both to set seconds
symbol s3        = bit18 ;b2
symbol s4        = bit19 ;b2
symbol s5        = bit20 ;b2
symbol s6        = bit21 ;b2
symbol s7        = bit22 ;b2
symbol s8        = bit23 ;b2    'toggle to turn on and off the ticker relay

symbol dataio    = b0 ;w0 and bit 0 to bit 7
symbol pad        = b1 ;w0 and bit 8 to bit 15
symbol iobuf    = w0 ;b0, b1
symbol keys        = b2 ;bit16 to bit 23
symbol fixaddr    = b3 ;start address for DE display

symbol Segment4LEFT    = b4  ;Rightmost 7 seg, LEFT Side
symbol Segment4RIGHT     = b5  ;Rightmost 7 seg, RIGHT Side
symbol Segment2LEFT    = b6  ;Leftmiddle 7 seg, LEFT Side
symbol Segment3LEFT    = b7  ;Rightmiddle 7 seg, LEFT Side
symbol Segment2RIGHT    = b8  ;Leftmiddle 7 seg, Right Side
symbol Segment3RIGHT      = b9  ;Rightmiddle 7 seg, Right Side
symbol Segment1LEFT      = b10 ;Leftmost 7 seg, LEFT Side
symbol Segment1RIGHT    = b11 ;Leftmost 7 seg, Right Side

symbol char        = b12
symbol bank        = b13
symbol tmpry     = b14
symbol dispbrit    = b15
symbol autoaddr    = b16
symbol readmode    = b17
symbol tmpry2    = b18
symbol EEPROMChar = b19
'w10 (b20/21) = used to read var from EEPROM
symbol LEDTicker  = b22

symbol seconds = b23 ' vars for RTC
symbol minutes = b24
symbol hours = b25
symbol blinky = b26 'for RTC 010000 would Enable output at 1Hz blink rate.  000000 is no blink
symbol junkread = b27 'used to read/write RTC day, month, year, date.  Also as a temp var in time set adjust routines

fixaddr        = $c0
dispbrit        = $88    '$88 (136DEC)  min bright.   $8F (143DEC) max bright
autoaddr        = $40
readmode         = $42

init:
high strobe            ;Ensure strobe is initially high
gosub clearchars        ;Clear all characters
blinky = 010000 ' 010000 would Enable output at 1Hz blink rate, start w/ relay click ON..  000000 is no blink.

' Set the time on the DS1307 RTC
i2cslave %11010000, i2cslow, i2cbyte    ; set PICAXE as master and DS1307 slave address
pause 50
'\/ \/ \/ \/ Un_REM THESE LINES (BELOW) IF SETTING UP A NEW RTC  \/ \/ \/ \/
#rem
' Set the RTC chip time
;  write time and date e.g. to 11:59:00 on Thurs 25/12/03
'; would be "writei2c 0,($00, $59, $11, $03, $25, $12, $03, 010000)"
' readi2c 0, (b0,b1,b2,b3,b4,b5,b6,b7) reads back the data

let hours = $19        ; 01-12 Note all BCD format
let minutes = $11         ; 00-59 Note all BCD format  
let seconds = $10    ; 00-59 Note all BCD format

; program does not use for we use seconds.  Set manually in the write statement
' for SQ Wave out on RTC.  Last val: 010000 would Enable output at 1Hz blink rate.  000000 is no blink

writei2c 0, (seconds, minutes, hours, 01, 01, 01, 01, blinky)
pause 50

#endrem
'/\ /\ /\ /\ Un_REM THESE LINES (ABOVE) IF SETTING UP A NEW RTC  /\ /\ /\ /\


;--------------------------------------------------------

'I have laid out the 8 segments in the display as:

'| Segment1LEFT | Segment2LEFT | Segment3LEFT | Segment4LEFT | Segment1RIGHT | Segment2RIGHT | Segment3RIGHT | Segment4RIGHT

    ;Segment Values                0-9   = ( 0 , 1,  2 , 3 , 4 , 5 , 6 , 7, 8 , 9,
    '                              10-19 =   A , b , C , d , E , F , g,  H, i,  J,
    '                              20-29 =   K,  L,  M,  N,  o,  P,  q,  r, S,  T, 
    '                              30-35 =   U, V, W,  X,  y,   Z ,
    '                              36-44 =   segA, segB, segC, segD, segE, segF, segG, dp, off)

'the 'gosub display' routine expect 8 values; SegmentxLEFT and SEGMENTxRIGHT coded as
'lookup values shown in the rem above.

main:

if s1 = 1 or s2 = 1 or s8 = 1 then 'setting the clock time or relay ticker
    if s1 = 1 and s2 = 0 then 'setting hours
        junkread = junkread + 1
        if junkread > 23 then
            junkread = 0
        end if
        lookup junkread, ($00,$01,$02,$03,$04,$05,$06,$07,$08,$09,$10,$11,$12,$13,$14,$15,$16,$17,$18,$19,$20,$21,$22,$23), hours
         i2cslave %11010000, i2cslow, i2cbyte
        writei2c 0, (seconds, minutes, hours, 01, 01, 01, 01, blinky)
        pause 10
    endif ' s1 = 1, setting hours
   
    if s2 = 1 and s1 = 0 then 'setting minutes
        junkread = junkread + 1
        if junkread > 59 then
            junkread = 0
        end if
        lookup junkread, ($00,$01,$02,$03,$04,$05,$06,$07,$08,$09,$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), minutes
         i2cslave %11010000, i2cslow, i2cbyte
        writei2c 0, (seconds, minutes, hours, 01, 01, 01, 01, blinky)
        pause 10
    endif 's2 = 1, setting minute
   
    if s1 = 1 and s2 = 1 then 'reset seconds to 00
        seconds = $00
        i2cslave %11010000, i2cslow, i2cbyte
        writei2c 0, (seconds, minutes, hours, 01, 01, 01, 01, blinky)
        pause 10
    endif 'settin seconds to zero

    if s8 = 1 then ' turn on/off the clicking relay
        'read the RTC to dected the seconds for the write to RTC below keeps them accurate
        i2cslave %11010000, i2cslow, i2cbyte    ; set PICAXE as master and DS1307 slave address
        readi2c 0,(seconds, minutes, hours, junkread, junkread, junkread, junkread, blinky)
        pause 10
        if blinky = 010000 then 'blinky from RTC is ON and clinking the relay. turn it OFF
            blinky = 000000
        else              'blinky from RTC is OFF and NOT clinking the relay. turn it ON
            blinky = 010000
        end if
        i2cslave %11010000, i2cslow, i2cbyte
        writei2c 0, (seconds, minutes, hours, 01, 01, 01, 01, blinky)
        pause 500
    end if
   

else ' not settign the clock, check for brightness adjust and run as normal; so read a new 4letter word
   
    if s7 = 1 then 'increase brightness
        dispbrit = 140 'other values cause random LED7 behavior
    end if

    if s6 = 1 then 'decrease brightness
        dispbrit = 136   ' 136 is min bright
    end if   

sertxd (#dispbrit, 13,10)
   
    'Get SegmentxLEFT values for clock by reading the RTC
    i2cslave %11010000, i2cslow, i2cbyte    ; set PICAXE as master and DS1307 slave address
    readi2c 0,(seconds, minutes, hours, junkread, junkread, junkread, junkread, blinky)
    pause 10
    gosub ReadEEPROM  ' read the four letter word.  These are loaded into SegmentxRIGHT vars
    gosub Ticker    'ticks thru the R/G LEDs to show seconds
endif

Segment1LEFT = hours & %11110000 / 16  'BCD so shift upper 4 bits to lower 4 bits
Segment2LEFT = hours & 001111

Segment3LEFT = minutes & %11110000 / 16   'BCD so shift upper 4 bits to lower 4 bits
Segment4LEFT = minutes & 001111

gosub display   'Put the SegmentxLEFT and SEGMENTxRIGHT characters onto the 7 seg displays.

gosub getkeys        ;Read tact buttons
           
goto main

'-------------------------------------------------------
Ticker: 'ticks thru the R/G LEDs to show seconds by cycling through each LED address

junkread = seconds & %11110000
junkread = junkread / 16 * 10
seconds = seconds & 001111
seconds = junkread + seconds

lookup seconds, (1,1,1,1,1,1,1,1,3,3,3,3,3,3,3,3,5,5,5,5,5,5,5,5,7,7,7,7,7,7,7,7,9,9,9,9,9,9,9,9,11,11,11,11,11,11,11,11,13,13,13,13,13,13,13,13,15,15,15,15), dataio

dataio = dataio + fixaddr    ;LEDs are at odd addresses 1 to 15
junkread = dataio   'used to turn off LED later in this sub
low strobe
gosub sendchar

LEDTicker = LEDTicker + 1

if LEDTicker = 2 then
    LEDTicker = 1
end if

dataio = LEDTicker  'Light the LEDs.  1 = RED.  2 = GREEN.  3 = R/G
gosub sendchar
high strobe

'Turn off LED here
dataio = junkread   
low strobe
gosub sendchar
dataio = 0   '0 turns off the currently selected LED
gosub sendchar
high strobe;

dataio    = dispbrit        ;Display control on, brightness level
low strobe                 ;Strobe low
gosub sendchar
high strobe                ;Strobe high

return 'Ticker




ReadEEPROM:
'24LC256 EEPROM is loaded with 987 four letters words (3948 characters)
'Each character is an address from 0 to 3947
'readi2c addrs, (charvalue)

i2cslave %10100000, i2cslow, i2cword    ; set PICAXE as master and DS1307 slave address

'Read and Translate the char read from the EEPROM for the lookup(.,...), dataio command.
'Read the EEPROM letter then subtract 87 from that ASCII value for the "lookupchar" sub.  Examples:
'ASCII value for a = 97; Lookup in this program value is 10.  So, 97 - 87 = 10
'ASCII value for j = 106; Lookup in this program value is 19.  So, 106 - 87 = 19
'ASCII value for k = 122; Lookup in this program value is 35.  So, 122 - 87 = 35


readi2c w10, (Segment1RIGHT)
Segment1RIGHT = Segment1RIGHT - 87

w10 = w10 + 1
readi2c w10, (Segment2RIGHT)
Segment2RIGHT = Segment2RIGHT - 87

w10 = w10 + 1
readi2c w10, (Segment3RIGHT)
Segment3RIGHT = Segment3RIGHT - 87

w10 = w10 + 1
readi2c w10, (Segment4RIGHT)
Segment4RIGHT = Segment4RIGHT - 87

w10 = w10 + 1
'check if "yurt" (the last possible word) is displayed?
if Segment1RIGHT = 34 AND Segment2RIGHT = 30 AND Segment3RIGHT = 27 AND Segment4RIGHT = 29 then 'yes. it is "yurt"
    w10 = 0   'yurt' found, so go back to address 0 (the first 4letter word)
end if

pause 1000 'keep the secs LED on and slow down the words

return ' ReadEEPROM


;--------------------------------------------------------

display:    ;Displays data on the 7 seg displays, using 2 blocks of 4 digits

    bank = 0   ;LEFT Side: First block of digits

    dataio    = fixaddr + bank + 0 ;Set Leftmost 7 seg, LEFT Side write address
    low strobe                 ;Strobe low
    gosub sendchar
    char = Segment1LEFT        ;Leftmost 7 seg, LEFT Side
    gosub lookupchar
    gosub sendchar
    high strobe                ;End of data - Strobe high
   
    dataio    = fixaddr + bank + 2 ;Set Leftmiddle 7 seg, LEFT Side write address
    low strobe                 ;Strobe low
    gosub sendchar
    char = Segment2LEFT        ;Leftmiddle 7 seg, LEFT Side
    gosub lookupchar
    gosub sendchar
    high strobe                ; End of data - Strobe high
   
    dataio    = fixaddr + bank + 4 ;Set Rightmiddle 7 seg, LEFT Side write address
    low strobe             ; Strobe low
    gosub sendchar
    char = Segment3LEFT    ;Rightmiddle 7 seg, LEFT Side
    gosub lookupchar
    gosub sendchar
    high strobe            ;End of data - Strobe high
   
    dataio    = fixaddr + bank + 6 ;Set Rightmost 7 seg, LEFT Side write address
    low strobe             ; Strobe low
    gosub sendchar
    char = Segment4LEFT    ;Rightmost 7 seg, LEFT Side
    gosub lookupchar
    gosub sendchar
    high strobe            ;End of data - Strobe high
   
    'RIGHT BANK
    bank = 8  ;RIGHT Side: Second block of 4 digits
    dataio    = fixaddr + bank + 0 ;Set Leftmost 7 seg, Right Side write address
    low strobe             ;Strobe low
    gosub sendchar
    char = Segment1RIGHT    ;Leftmost 7 seg, Right Side
    gosub lookupchar
    gosub sendchar
    high strobe            ;End of data - Strobe high
   
    dataio    = fixaddr + bank + 2 ;Set Leftmiddle 7 seg, Right Side write address
    low strobe             ;Strobe low
    gosub sendchar
    char = Segment2RIGHT    ;Leftmiddle 7 seg, Right Side
    gosub lookupchar
    gosub sendchar
    high strobe            ;End of data - Strobe high
   
    dataio    = fixaddr + bank + 4 ;Set Rightmiddle 7 seg, Right Side write address
    low strobe             ; Strobe low
    gosub sendchar
    char = Segment3RIGHT    ;Rightmiddle 7 seg, Right Side
    gosub lookupchar
    gosub sendchar
    high strobe            ; End of data - Strobe high
   
    dataio    = fixaddr + bank + 6 ;Set Rightmost 7 seg, RIGHT Side write address
    low strobe             ; Strobe low
    gosub sendchar
    char = Segment4RIGHT    ;Rightmost 7 seg, RIGHT Side
    gosub lookupchar
    gosub sendchar   
   
    '-----------------
   
    'must refresh dispbrit each time
    dataio    = dispbrit ;Display brightness level. $88 (136DEC)  min bright.   $8F (143DEC) max bright
    low strobe         ; Strobe low
    gosub sendchar
    high strobe        ; Strobe high

return   'display

;--------------------------------------------------------

clearchars:            ;Clear LEDs and 7 seg displays.  ALL LEDS OFF. Segs and LEDs
    dataio    = autoaddr ; Data mode auto increment
    low strobe         ; Strobe low
    gosub sendchar
    high strobe        ; Strobe high
    ;
    low strobe         ; Strobe low
    dataio    = fixaddr ; Set start address
    gosub sendchar
    for tmpry = 1 to $0f    ;$0F = 15, so loop runs 16 times.  7 LEDs and 7 seg displays
        dataio = 0        ;Zero blanks the  display
        gosub sendchar
    next
    high strobe            ;Strobe high, keep low to end of data
return

;--------------------------------------------------------

sendchar:    ;Routine to send all characters to LKM1638 module serially
    pad        = $ff    ;$FF = 255.  Set counter
    high clock        ;Ensure clock is high for pulseout
    do
      pinc.1 = bit0    ;Make c.1 the value in bit0
      iobuf = iobuf/2    ;Shift right
      pulsout clock,1 '10us clock pulse
    loop Until pad = 0  'excecute 256 times
return

;--------------------------------------------------------

getkeys:    ;Reads the input tact buttons in and places them in bits16 to bits23
dataio    = readmode    ; Data mode read
low strobe
gosub sendchar
input c.1            ;set c.1 as input
high clock            ;Ensure clock is high for pulseout
for tmpry = 1 to 16    ;Read in bits 0-15
    bit0 = pinc.1    ;Make bit0 the value on c.1. Need to use c.1 as it is both in & out
    iobuf = iobuf*2    ;Shift bit left
    pulsout clock,1    ;10us clock pulse, read next bit
next
s6 = bit3            ;Move 1st word switch values out of buffer
s2 = bit7
s5 = bit11
s1 = bit15
for tmpry = 1 to 16    ;Read in bits 16-31
    bit0 = pinc.1    ;Make bit0 the value on b.0. Need to use c.1 as it is both in & out
    iobuf = iobuf*2    ;Shift bit left
    pulsout clock,1    ;10us clock pulse, read next bit
next
s8 = bit3            ;Move 2nd word switch values out of buffer
s4 = bit7
s7 = bit11
s3 = bit15   
output c.1            ;Return c.1 to output
high strobe
return

;--------------------------------------------------------

lookupchar:    ;Looks up the code to display the digit in 'char' on the 7 seg display
    ;character  0-9   =    ( 0 , 1,  2 , 3 , 4 , 5 , 6 , 7, 8 , 9,
    '               10-19 =         A , b , C , d , E ,  F , g,  H, i,   J,
    '               20-29 =         K,  L,  M,  N, o,   P,  q,  r,  S,  T, 
    '               30-35 =         U, V, W,  X,  y,   Z ,
    '               36-44 =        segA, segB, segC, segD, segE, segF, segG, dp, off)

    lookup char,(63,6,91,79,102,109,125,7,127,111,119,124,57,94,121,113,111,118,16,30,118,56,21,84,92,115,103,80,109,120,62,28,42,118,110,91,1,2,4,8,16,32,64,128,0),dataio

return
;-----------------------------------------
-----
Link back: Hack A Day
-----