Wednesday, July 11, 2012

Repurpose an Old Disk Drive as a Microcontroller Input Device

Every geek either has and old disk drive or soon will. Here is a way to repurpose that disk drive as an input device for a microcontroller project. This example just shows the disk drive blinking an LED. But you get the idea; with some creativity there are many applications. It's so easy it barely qualifies as a hack, but here are the details.
-----
The device that makes a disk drive spin is a DC spindle motor. If you spin the spindle motor a current is produced. Search youtube for LED Stepper flashlight, etc. and you will find many examples of this experiment.

We need to get two of the spindle motor wires on the disk drive ultimately into the microcontroller.  Take the drive apart and make connections to two of the spindle motor wires.  In the pic you see where we soldered small wires to middle spindle motor connection points.  The other end of these two wires are soldered to two of the drives header pins. This makes for a handy way to plug in a JST connector.

-----
Below is a 'scope shot of what the output signal looks like when you spin the spindle motor.  A purist might consider rectifying the output to keep the microcontroller from seeing a negative voltage.  Since the max output is maybe 500mV, I didn't worry about it.
-----
Here is the custom code for the microcontroller; a PICAXE-08M2.  An Analog to Digital Convertor (ADC) input is monitored.  If a signal is detected of the ADC from the spinning disk drive then flash an LED.  Short and simple.

#picaxe08m2
low 2                'LED on output 2.  Make certain it is off
main:                'Start of main program loop
readadc 1, b0   'Read value of ADC on input 1.  Store in b0
if b0 > 1 then   'If there is a signal on the ADC, the disk is spinning so LED on
toggle 2
pause 50
endif
goto main
----
Thanks for the visit!!!
-----
Link back: Hack A Day
-----

Friday, July 6, 2012

Using a MicroController to Train a Cat

Most of the time Kelso is a great cat.  A few examples of his awesomeness can be seen here, here, and here.  However, he still seems to squeeze in some mischief despite a rigorous schedule that includes sleeping 18 hours a day.

For example, we spotted some paw prints on the stove vent hood.  But wait... Kelso is strictly forbidden to even think about getting on the counters so it couldn't have come from him.  Impossible.  Up goes a security camera to gather more evidence:
-----
Busted!  We need a solution and it needs to be high tech.  

A quick search of the spare parts bin at "The Lab" yields a PICAXE 28X1 custom programmable microcontroller, a piezo speaker (that is really really loud!), a Sharp InfraRed Rangefinder, and a AA battery holder.
-----
All of that stuff in the picture is useless as a solution without some simple custom programming.  Basically, we coded the PICAXE 28X1 to continually monitor the Sharp InfraRed Rangefinder to see if Kelso is in front of it.  If he is, blast five LOUD chirps through the piezo speaker then rearm and wait.  The code was easy and straightforward; less that 20 lines.  The only thing special we did was turn off the PICAXE 28X1 brown out detection (disablebod) and slow the internal clock down from 4MHz to 31KHz in an effort to extend battery life.  Here is a pic of the finished rig that will keep Kelso from ever misbehaving again. ;)

-----
And here is demo of the rig in action:


-----
Does it work?  Hell yes it does!!!
Thanks for checking out the build.
-----
Link back: Hack A Day
Link back: Hatched Gadgets
-----

Saturday, June 23, 2012

"Etch a Sketch" Turned Temperature Data Logger

A friend of mine gave me an OKI office printer.  The thing was HUGE and after about five years it finally broke.  Next step, out comes the screwdriver to rescue any useful parts; of which where several stepper motors.  Since what I didn't know about stepper motors was a lot I searched for a "useful" way to learn about them.  I decided to connect two of the stepper motors to an "Etch a Sketch" and ended up with this rig that graphically logs temperature in a strip chart fashion.


Here is a video if you are not interested in the build details and just the want to see the result.  The beer was cold.  The water in the shot glass hot.  Hot makes the graph go up.  Cold makes the graph go down.  When the graph reaches the far right of the "Etch a Sketch" the stylus moves full left and the process repeats.  In the video a temperature measurement is taken (and graphed) every 750 milliseconds, but that can be adjusted to anything; one reading per hour for example. 


-----
The process of driving the steppers was not trivial in the beginning.  First, I had no documentation on these steppers.  The second being I had no idea how "noisy" and power hungry the steppers could be.    The documentation turned out not to be a big deal.  Via the magic of the internet I learned they were of 4-wire, bi-polar configuration.  An ohm meter is all that is needed to figure out the connection scheme. 

----
Close up of one of the OKI printer 4-wire bipolar stepper motors:

-----
Driving a stepper motor requires a microcontroller.  My choice for a microcontroller was the PICAXE 18M2.  
-----
A stepper motor is not like a 'common' DC motor.  You cannot just apply a current and have the stepper spin.  The current has to be applied in sequence across the four available wires.  You also have to control the polarity (direction) of the current.  That said, steppers motors take way more current than a microcontroller can provide.  An H-Bridge motor driver solves the problem by providing more available drive current for the stepper and the ability to switch current drive polarity.

I was familiar with the SN754410NE H-Bridge motor driver.  Plus, I had some in my kit.  So, originally I decided to use one SN754410NE to drive each stepper motor.  This was a mistake that added much frustration.  The stepper motors are incredibly noisy and current hungry.  The noise caused by the steppers and energy from their back EMF (I think) caused nothing to work reliably.  After seeing on a datasheet that L293D motor drivers have protection diodes and some other features, I gave them a try instead.  The L293D is pin compatible with the SN754420NE so the swap was easy.  After inserting the L293D's everything started moving forward as planned with controlling the steppers.


-----
Now that we can control the stepper motors via the PICAXE 18M2 and L293D's we still need to interface then some way to the "Etch a Sketch".  I had a clear plastic cube thats purpose was to protect a trophy baseball.  Since I didn't have a trophy baseball I dismantled the cube and used the two "C" shaped pieces to mount the steppers to with the help of a Dremmel tool and double sided sticky tape.
-----
After mounting the steppers motors, you still have to mechanically couple them to the "Etch a Sketch".  Rubber hose and zip tie wraps worked perfectly.
-----
After getting the mechanicals figured out a "test" pattern was programmed into the PICAXE.  The test worked on the first run so we grabbed the video camera to document the success.


-----
Now that the stepper motors make the "Etch a Sketch" draw, we still need a way to measure temperature.  The PICAXE 18M2 is used to read a DS18B20 sensor (picture below) via I2C bus for this:

-----
To manually position the "Etch a Sketch" stylus, two buttons are wired into the PICAXE 18M2:
-----
After all of that it is just code and software debugging. 

I have other plans for the rig.  Stay tuned!
-----
If you are still with me, here is the build schematic (click to enlarge):
-----

Sunday, June 3, 2012

Swim Heat Counter with PICAXE 08M2

A friend of mine had the exciting job of flipping cards to display heats at his daughter's swim tournament.  Not difficult to do, but it doesn't allow the much mobility for the person assigned to the job.  Wouldn't it be nice to modernize the task and make it wireless?
-----
With a PICAXE 08M2 microcontroller and a few servos the electrical part of the task is pretty simple.   Basically two buttons (a ONES place button and a TENS place button) pull an input to the PICAXE high, causing a subroutine to be called and the appropriate servo to move.  Adding wireless to the rig should be easy as well by re-purposing a cheap remote from a toy RC car to replace the two button/switches that cause the servos to move. 

Adding the mechanical digits will not be completely trivial, by my buddy says he is up to the challenge.
-----
 Short video of the rig in action.
-----
Schematic drawing of the build (click to increase size):
-----
PICAXE 08M2 Project Source Code.  Very simple:

#rem
 *******************************
 ***** www.WhiskyTangoHotel.Com  *****
 *******************************
    Project Name: Walker Swim Heat Counter

    Start Date: June 1, 2012
    
    Program Rev History: 
    This version steps the a ONES digit Servo and a
    TENS digit Servo in ten increments to "display"
    the numbers 00-99.

 ******************************* 
    PICAXE PE Rev: 5.5.1
#endrem

#picaxe08m2 ' using PICAXE 08M2 uC
#COM11 'programming on COM11

'min servopos value = 75
'center servopos value = 150
'max servopos value = 255

symbol Ones_Button = pinc.4 'input button for Ones digit.  Pull high to count
symbol Ones_Position = b0 'servo location var


symbol Tens_Button = pinc.3 'input button of Tens digit.  Pull high to count
symbol Tens_Position = b1 'servo location var

'b2 is variable used for math in calculating both servo positons

'Init some stuff...
let dirsC = %11000111  ' define I/O of PortC.  Not really required.

servo 1,150 ; initialise ones digit servo
servo 2,150 ; initialise tens digit servo
Ones_Position = 0
'Calculate and move Ones digit Servo to "display" 0
b2 = Ones_Position * 15 + 75
servopos 1, b2

Tens_Position = 0
'Calculate and move Tens digit Servo to "display" 0
b2 = Tens_Position * 15 + 75
servopos 2, b2

main: 'main loop continually checks if a button is pushed to move the Servos.
If Ones_Button = 1 then 'move servo for Ones Digit
gosub Change_Ones
endif

If Tens_Button = 1 then 'move servo for Tens Digit
gosub Change_Tens
endif

goto main 'loop and check for button presses


Change_Ones: 'Routine called when "Ones" button is pressed.
If Ones_Position = 9 then 'highest position is '9'.  Wrap to '0'
Ones_Position = 0
else
Ones_Position = Ones_Position + 1
endif
'Convert the Ones_Position into the correct servo location
let b2 = Ones_Position * 15 + 75
Select Case b0
Case 0
servopos 1, b2
Case 1
servopos 1, b2
Case 2
servopos 1, b2
Case 3
servopos 1, b2
Case 4
servopos 1, b2
Case 5
servopos 1, b2
Case 6
servopos 1, b2
Case 7
servopos 1, b2
Case 8
servopos 1, b2
Case 9
servopos 1, b2
endselect
pause 500 'delay 500mSec to allow the servo to move
return ' Change_Ones

Change_Tens: 'Routine called when "Tens" button is pressed.
If Tens_Position = 9 then 'highest position is '9'.  Wrap to '0'
Tens_Position = 0
else
Tens_Position = Tens_Position + 1
endif
'Convert the Tens_Position into the correct servo location
let b2 = Tens_Position * 15 + 75
Select Case b0
Case 0
servopos 2, b2
Case 1
servopos 2, b2
Case 2
servopos 2, b2
Case 3
servopos 2, b2
Case 4
servopos 2, b2
Case 5
servopos 2, b2
Case 6
servopos 2, b2
Case 7
servopos 2, b2
Case 8
servopos 2, b2
Case 9
servopos 2, b2
endselect
pause 500  'delay 500mSec to allow the servo to move
return 'Change_Tens
-----

Friday, May 25, 2012

Progression of a PICAXE LED Chaser (Knight Rider) LED Display

There was a question on the PICAXE forum asking about building up a "Knight Rider" display.  The '80s TV show "Knight Rider" featured a 1982 Pontiac Trans Am named "KITT" that had some blinky lights mounted in the hood that somehow let the car solves crimes and do some other amazing stuff.  Pretty impressive technology for an early '80s American car!

-----
The authentic way to do the "KITT" display is to show LEDs moving back and forth by turning a "main" LED on full bright and surround that full bright LED with progressively dimmer LEDs.  That is not that hard to do using the PWM (Pulse Width Modulation) features of the PICAXE, but I thought there may be an easier way.

I wanted to test a simpler way to simulate the display on "KITT" by just turning the LEDs on/off in sequence quickly.  I was also interested in experimenting with the PICAXE "let dir", "let pins", and "lookup" and this seemed like an easy platform to do this.  In the first attempt a PICAXE 18M2 was used to simulate an eight LED "KITT" display.  The result was surprisingly excellent.  To me, the PWM is not really needed due to the persistence for your vision and the LEDs.  An ADC input on the PICAXE was used to allow for an adjustable delay on how fast the display moves.  Here is a short video of the results:

The original forum question was asked by Jacob2803.  He gave it a try with my code as well and here is a short youtube video of his nice result:  http://www.youtube.com/watch?v=HwoHKqRI-sY
-----
After seeing an eight LED Chaser display the discussion of using more LEDs came up.  More is always better, right?.  The PICAXE forum is an interesting place.  It has participation of users from all levels; beginner to expert, and the brainstorming of solutions (on many problems) can be inspiring.  Many options were provided on increasing the LED count.  My thought on increasing the count on the LED Chaser display was to use the PICAXE 08M2 and the 74154 (4:16 Decoder).  The PICAXE 08M2 has fewer outputs than the 18M2 that was used above, but the 74154 only needs four control signals to turn on any one of 16 LEDs at a time.

Here is a picture and short video of what the 16 LED Chaser looked like on the development board:

-----
The 16 LED Chaser looked so cool, I decided to move it to a PCB and keep it "forever".  It barely looks like it has any similarity to the development board build.  Since the circuit is very minimal it cleans up well on the PCB.
-----
I programmed a few different chaser patterns into the PICAXE that can be selected with a button press.  Here is a short video of the PCB version of the 16 LED Chaser in action.
-----
My code and schematic is below in case you want to build your own.  If you build it and mount it to a 1982 Pontiac Trans Am please send us a pic.  ;)

Schematic:

PICAXE Code:

#rem
 *******************************
 ***** www.WhiskyTangHotel.Com  *****
 *******************************
    Project Name: 16 LED Chaser with 08M2 and 74590 Decoder

    Start Date: May 18, 2012

 *******************************
    PICAXE PE Rev: MacAXEPad 1.3.2
 
#endrem

#picaxe08m2
let dirsC = %11110111
'b0 is used as a general loop counter
Symbol StepDelay = b1
Symbol WhatCase = b2
Symbol MaxCases = b3 'Init value set below.  The # of possible display cases select routines programmed
'w2 (b4 and b5) used in random LED Case Select
Symbol ButtonPush = pinC.3

'Initialize some values
StepDelay = 20  ' Time to keep the only sigle LED the 74590 can turn on until moving to the next LED

Whatcase = 4    'Case Select routine that 'kicks things off' after reset
MaxCases = 4    '# of possible display cases select routines programmed.

main:
if ButtonPush = 1 then 'jump to a different Case Select routine
pause 25
Do While ButtonPush = 1
pause 25
loop
pause 25

if WhatCase = MaxCases then
let WhatCase = 0 ' reset WhatCase if it is equal the # of possible display cases programmed
endif
WhatCase = WhatCase + 1
endif

Select Case WhatCase

Case 1  'LEDs scan up and repeat
gosub LEDsUp

Case 2   'LEDs scan down and repeat
gosub LEDsDown

Case 3 'LEDs scan up the down and repeat.  This simulates the display on the "KITT" car in KnightRider
gosub LEDsUp
gosub LEDsDown

Case 4  'randomly turn on one LED at a time
gosub LEDRandom

end select

goto main

'LED pattern subroutines here.  Of course, more case routines can be added.
LEDsDown:
for b0 = 0 to 7
let pinsC = b0
pause StepDelay
next b0
'jump to 16 to turn on bit position 5
for b0 = 16 to 23
let pinsC = b0
pause StepDelay
next b0
return 'LEDsDown

LEDsUp:
for b0 = 23 to 16 step -1
let pinsC = b0
pause StepDelay
next b0

for b0 = 7 to 0 step -1
let pinsC = b0
pause StepDelay
next b0
return 'LEDsUp

LEDRandom:
RANDOM w2
let pinsC = w2 // 23 + 1 '"//" is modulus divide (returns remainder)
return 'LEDRandom
-----

Friday, March 23, 2012

Voltmeter Clock w/ F°, C°, and K° temperature readout.

-----
The objective was to create a real time clock using three analog voltmeters controlled via Pulse Width Modulation (PWM) to display "hours", "minutes", and "seconds".  At the press of a button the three meters display temperature in degrees F, C, and K.
-----
Here is a short (time lapse) video of the rig in action:


-----
There are four major components to the build.

  • PICAXE 14M2 microcontroller
  • DS1307 Real Time Clock (RTC) module
  • DS18B20 Temperature Sensor
  • Three 0-2VDC analog voltmeters (refaced to display as "hours", "minutes", and "seconds")
-----
The meters were taken apart to install custom faces.  A free program called "MeterBasic" was used to create the custom faces for the three voltmeters (see pic below).  Note that the meters have labeling to display temperature in degrees F, C, and K.
-----
See the black button below the "seconds" meter?  Pressing this button causes the meters to display their respective temperature.  
-----
Here are a few shots of the build process.  The "red thing with the black tip" is the DS18B20 temperature sensor.  In front of the meter in the middle (what will be the minutes meter), you can see a small PCB with two buttons.  These are used to set the time on the DS1307 Real Time Clock.  Pressing both buttons will set the seconds to zero.
------
The digital outputs on the PICAXE 14M2 put out about 5VDC maximum.  Our analog voltmeters only go to 2VDC maximum.  We set up a voltage divider circuit and a trimpot to allow the output from the PICAXE 14M2 to read full on our 2VDC meter.  The 100K trimpot (the little blue things in the pic below) allow for precise adjustment of the full scale reading.  Pushing the hour set, minute set, and read temperature button at the same time will force all meters to full scale.  This is to provide for precise tuning of the trimpots to calibrate the full scale reading of each meter.

After we have calibrated the meters to read "0" with no voltage and "full scale" from a high digital output on the PICAXE 14M2 we still have to be able to control the meters to display the time.  This is done by reading the time on DC1307 RTC via the I2C bus and the PICAXE 14M2.  Pulse Width Modulation control is used to convert the time (hours, minutes, and seconds) into a corresponding "average" voltage.  That PWM signal drives the three meters to display time.  The PICAXE 14M2 has four PWM output drivers that are well up to the job for this.

-----
Here is another look at the time set buttons.  They are located on the bottom side of the clock enclosure.
-----
The rig is powered by a rescued wall wart from an old Sony CD player.  The wall wart puts out 9VDC which is tamed to 5VDC with a LM7805 voltage regulator.
-----
If you want to build your own, the schematic looks like this.  The source code is below.
-----
Another pic of the finished rig.




















-----
If you're still with us, here the PICAXE code:
; *******************************
; ***** www.whiskeytangohotel.com *****
; *******************************
;    Project Name: 3 Panel Meter Clock
; REV: FIN (everything works fine with clock and temp)
;
;    Start Date:  Feb 12, 2012
;    
;    Program Rev History/Ideas:
; - to set clock push M or H button
; - push main button to display temp F, C, and K
; - Routine to drive 3 meters to full scale when main button AND (M OR H)
; is pressed.  This is to allow adjustment of trimmers to full scale.
; Adjustment to zero scale should be done first with power off.
;
; ******************************* 
;    PICAXE PE Rev: MacAXEPad 1.3.2
;
#picaxe14m2

'define memory locations as symbols
symbol hour_meter = c.0 'LEG 7
symbol minute_meter = c.2 'LEG 5
symbol second_meter = b.2 ' LEG 11
symbol temp_switch = pinc.4 ' LEG3
symbol temp_sensor = b.5 'LEG8
symbol hour_set = pinc.3 'LEG3
symbol minute_set = pinc.1 'LEG6

symbol CthermoValue = b10
symbol FthermoValue = b11
symbol KthermoValue = w6 'b12 and b13
symbol seconds = b0
symbol minutes = b1 
symbol hours = b2
symbol day = b3
symbol date = b4
symbol month = b5
symbol year = b6
symbol blinky = b7
symbol Tens_Digi = b8   ;Used to get the Tens Digit from the $HEX RTC value
symbol Ones_Digi = b9 ;Used to get the Ones Digit from the $HEX RTC value
' w7 (b14 and b15) is used to control the PCM to the meters 

' Set the time on the DS1307 RTC
i2cslave %11010000, i2cslow, i2cbyte ; set PICAXE as master and DS1307 slave address
pause 50 

'Set all meters to full scale with 100% duty cycle
pwmout hour_meter,99,400        
pwmout minute_meter,99,400    
pwmout second_meter,99,400   


'\/ \/ \/ \/ 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 seconds = $00 ; 00-59 Note all BCD format
let minutes = $00     ; 00-59 Note all BCD format   
let hours = $01 ; 01-12 Note all BCD format
let day = $03     ; program does not use date, date, month, year
let date = $22      
let month = $03  
let year = $12      
let blinky = 000000 ; 010000 would Enable output at 1Hz blink rate.  000000 is no blink

writei2c 0,(seconds, minutes, hours, day, date, month, year, blinky)
pause 50 
#endrem
'/\ /\ /\ /\ Un_REM THESE LINES (ABOVE) IF SETTING UP A NEW RTC  /\ /\ /\ /\


; POWER ON SELF TEST.  Send all three meters to FULL Scale and back to 0
'NOTE:  pwmduty hour_meter, w7  ---->> w7 ranges from 0 to 400 to move meter from 0VDC to 2VDC
for w7 = 400 to 0 step -1' pwmduty needs a (W)ord var, not a (B)yte var
pwmduty hour_meter, w7 'adjust PWM Duty from 100% to 0% 
pwmduty minute_meter, w7
pwmduty second_meter, w7
next w7


main:

if temp_switch = 1 then
do ' while hour_set = 1 or minute_set = 1 then 'if main buttom and H or M set button pushed then
pwmduty hour_meter, 400 ' move all meters to full scale to allow trimmer adjust.  Do 0 meter adjust  1st with power off.
pwmduty minute_meter, 400
pwmduty second_meter, 400
loop while hour_set = 1 or minute_set = 1
end if ' temp_switch = 1

if temp_switch = 1 and hour_set = 0 and minute_set = 0 then
do 'while temp_switch is pressed
gosub DisplayTemp
loop while temp_switch = 1 and hour_set = 0 and minute_set = 0
end if

'read the RTC and display the time
readi2c 0, (seconds, minutes, hours, day, date, month, year, blinky)
pause 10
'\/ \/ \/ \/ \/ SECONDS SECONDS SECONDS \/ \/ \/ \/ \/
;Convert the Seconds from the RTC to Base10 and update the meter
if temp_switch = 0 and minute_set = 1 and hour_set = 1 then 'all pressed.  Seconds to $00
gosub Seconds_set
end if 

Ones_digi = seconds & 0x0F   ' zero out the top four bits

Tens_Digi = seconds & 0xF0   ' zero out the lower four bits
Tens_Digi = Tens_Digi / 2 ' each divide by 2 shifts the 
Tens_Digi = Tens_Digi / 2 ' bits LEFT.  Four shift get
Tens_Digi = Tens_Digi / 2 ' them all to the lower four bits
Tens_Digi = Tens_Digi / 2
Tens_Digi = Tens_Digi * 10 'Now shift the Base10 value to Tens place

seconds = Tens_Digi + Ones_Digi 'complete. Now $ss is ss (in Base10)
' Update the seconds meter with a w9 value of 0 to 400
w7 =  seconds * 677 / 100  ; (400/59=6.77) scale 0-59 seconds to 0-400 for PWM
pwmduty second_meter, w7
'/\ /\ /\ /\ SECONDS END /\ /\ /\ /\ /\ /\ /\

'\/ \/ \/ \/ MINUTES MINUTES MINUTES \/ \/ \/ \/ \/
if temp_switch = 0 and minute_set = 1 and hour_set = 0 then 'if temp_switch and M is pressed then add on minute
gosub Minutes_set
end if 
;Convert the Minutes from the RTC to Base10 and update the meter
Ones_digi = minutes & 0x0F   ' zero out the top four bits

Tens_digi = minutes & 0xF0   ' zero out the lower four bits
Tens_Digi = Tens_Digi / 2 ' each divide by 2 shifts the 
Tens_Digi = Tens_Digi / 2 ' bits LEFT.  Four shift get
Tens_Digi = Tens_Digi / 2 ' them all to the lower four bits
Tens_Digi = Tens_Digi / 2
Tens_Digi = Tens_Digi * 10 'Now shift the Base10 value to Tens place

minutes = Tens_Digi + Ones_Digi 'complete. Now $mm is mm (in Base10)
'Update the minutes meter with a w9 value of 0 to 400
If minute_set = 0 then 'dont update if we are setting the minutes.  Should correct this in Minutes_set routine
w7 = minutes * 677 / 100 ; (400/59=6.77) scale 0-59 minutes to 0-400 for PWM
pwmduty minute_meter, w7
end if 
'/\ /\ /\ /\ /\ MINUTES END /\ /\ /\ /\ /\

'\/ \/ \/ \/ \/ HOURS HOURS HOURS \/ \/ \/ \/
if temp_switch = 0 and minute_set = 0 and hour_set = 1 then 'if temp_switch and M is pressed then add on minute
gosub Hours_set
end if 

;Convert the Hours from the RTC to Base10 and update the meter
Ones_digi = hours & 0x0F   ' zero out the top four bits

Tens_digi = hours & 0xF0   ' zero out the lower four bits
Tens_Digi = Tens_Digi / 2 ' each divide by 2 shifts the 
Tens_Digi = Tens_Digi / 2 ' bits LEFT.  Four shift get
Tens_Digi = Tens_Digi / 2 ' them all to the lower four bits
Tens_Digi = Tens_Digi / 2
Tens_Digi = Tens_Digi * 10 'Now shift the Base10 value to Tens place

hours = Tens_Digi + Ones_Digi 'complete. Now $hh is hh (in Base10)

if hours > 12 then
hours = hours - 12
end if
if hours = 0 then 
hours = 12
end if

' Update the hours meter with a w9 value of 0 to 400
w7 = hours * 3636  ; (400/11 = 36.36)  scale 1 to 12 hours to 0-400 for PWM
w7 = w7 - 3636 'subtract  y interceot to start PCM at 0 to 1 o'clock.
w7 = w7 / 100 'scale 1 to 12 hours to 0-400 for PWM
pwmduty hour_meter, w7
'/\ /\ /\ /\ /\ HOURS END /\ /\ /\ /\ /\
goto main

DisplayTemp: 
readtemp temp_sensor, CthermoValue
w7 = CthermoValue * 677 / 100 '(400/59=6.77) scale C to 0-400 for PWM
pwmduty minute_meter, w7 'C (raw) in the minutes meter)

'Convert C to F
FthermoValue = 9 * CthermoValue / 5 + 32
w7 = FthermoValue * 364  ; (400/11 = 36.36)  scale 10 to 120F  to 0-400 for PWM
w7 = w7 - 3636 'subtract  y interceot to start PCM at 0 to 10F
w7 = w7 / 100 'scale 0-400 for PWM
pwmduty hour_meter, w7 '(F (x10) on the hours meter


'Convert C to K
KthermoValue = CthermoValue + 273
w7 = KthermoValue / 10
w7 = w7 * 677 / 100 
pwmduty second_meter, w7 'Kelvin *100 on the seconds meter

return 'DisplayTemp

Seconds_Set:
seconds = $00
writei2c 0,(seconds, minutes, hours, day, date, month, year, blinky)
pause 50 
w7 =  seconds * 677 / 100  ; (400/59=6.77) scale 0-59 seconds to 0-400 for PWM
pwmduty second_meter, w7
return 'Seconds_set

Minutes_Set:
readi2c 0, (seconds, minutes, hours, day, date, month, year, blinky)
;Convert the Minutes from the RTC to Base10 and update the meter
Ones_digi = minutes & 0x0F   ' zero out the top four bits
Tens_digi = minutes & 0xF0   ' zero out the lower four bits
Tens_Digi = Tens_Digi / 2 ' each divide by 2 shifts the 
Tens_Digi = Tens_Digi / 2 ' bits LEFT.  Four shift get
Tens_Digi = Tens_Digi / 2 ' them all to the lower four bits
Tens_Digi = Tens_Digi / 2
Tens_Digi = Tens_Digi * 10 'Now shift the Base10 value to Tens place
minutes = Tens_Digi + Ones_Digi 'complete. Now $mm is mm (in Base10)
minutes = minutes + 1
if minutes > 59 then
minutes = 0
end if
'convert base10 minutes to BCD here then write new minute value to RTC
Ones_Digi = minutes // 10
Tens_Digi = minutes - Ones_Digi
Tens_Digi = Tens_Digi / 10
Tens_Digi = Tens_Digi * 2  ' shift the lower right bits
Tens_Digi = Tens_Digi * 2  ' to the upper left.
Tens_Digi = Tens_Digi * 2
Tens_Digi = Tens_Digi * 2
Tens_Digi = Tens_Digi OR Ones_Digi 'OR function on the two values to get 8 bit BDC
'Now Ten_digi = minutes in packed BCD.  Just using Tens_Digi as a temp var
writei2c 0,(seconds, Tens_Digi, hours, day, date, month, year, blinky)
pause 50 
'Update the minutes meter with a w9 value of 0 to 400
w7 = minutes * 677 / 100 ; (400/59=6.77) scale 0-59 minutes to 0-400 for PWM
pwmduty minute_meter, w7
pause 500
return ' Minutes_Set

Hours_Set: 'HOURS SET WORKS PERFECT
readi2c 0, (seconds, minutes, hours, day, date, month, year, blinky)
;Convert the Hours from the RTC to Base10 and update the meter
Ones_digi = hours & 0x0F   ' zero out the top four bits
Tens_digi = hours & 0xF0   ' zero out the lower four bits
Tens_Digi = Tens_Digi / 2 ' each divide by 2 shifts the 
Tens_Digi = Tens_Digi / 2 ' bits LEFT.  Four shift get
Tens_Digi = Tens_Digi / 2 ' them all to the lower four bits
Tens_Digi = Tens_Digi / 2
Tens_Digi = Tens_Digi * 10 'Now shift the Base10 value to Tens place
hours = Tens_Digi + Ones_Digi 'complete. Now $hh is hh (in Base10)
hours = hours + 1
if hours > 12 then
hours = hours - 12
end if
if hours = 0 then 
hours = 12
end if

if hours > 9 then
if hours = 10 then 
hours = $10
end if
if hours = 11 then
hours = $11
end if
if hours = 12 then
hours = $12
end if
end if
writei2c 0,(seconds, minutes, hours, day, date, month, year, blinky)
pause 50 
;Convert the Hours from the RTC to Base10 and update the meter
Ones_digi = hours & 0x0F   ' zero out the top four bits
Tens_digi = hours & 0xF0   ' zero out the lower four bits
Tens_Digi = Tens_Digi / 2 ' each divide by 2 shifts the 
Tens_Digi = Tens_Digi / 2 ' bits LEFT.  Four shift get
Tens_Digi = Tens_Digi / 2 ' them all to the lower four bits
Tens_Digi = Tens_Digi / 2
Tens_Digi = Tens_Digi * 10 'Now shift the Base10 value to Tens place
hours = Tens_Digi + Ones_Digi 'complete. Now $hh is hh (in Base10)
' Update the hours meter with a w9 value of 0 to 400
w7 = hours * 3636  ; (400/11 = 36.36)  scale 1 to 12 hours to 0-400 for PWM
w7 = w7 - 3636 'subtract  y interceot to start PCM at 0 to 1 o'clock.
w7 = w7 / 100 'scale 1 to 12 hours to 0-400 for PWM
pwmduty hour_meter, w7
pause 1000

return ' Hours_Set
-----

Sunday, February 19, 2012

Simple LED Light from Spare Parts

A piece of flat aluminum stock, an old heat sink, a switch, and two cheap automotive tail light LEDs. Put them together and get this:
-----

-----
-----
-----

-----