From time to time I order kits to make, sometimes to see how they are put together, other times because I am interested in a particular result (e.g. a little Christmas decorative tree) but oftentimes the final product may be of some use.
In this instalment of "why did I order that?" I put together a kit for a frequency tester.
When it comes to fact checking, it is of course important to consider "Who watches the watcher?" and this kit does allow a form of calibration whereby the actual frequency of the 20MHz reference crystal can be taken into account for the measurement.
Of course temperature drifts and other factors could mean that calibration may need to be done a number of times before/during usage.
If you want to buy one of these handy little units and/or need a refresher on usage then see this link and/or this link, as for this video and blog I concentrated this time on the construction and (quick!) testing of this kit.
The old man version of the Pesky Padauk Programmer is almost dead. Although in a previous blog and video I was able to talk to the STM32 and thus load the firmware onto this board - I was not able recognise or program any Padauk Chips <grrrrrr>.
In a parallel approach (multitask!) I bought a cheap oven and started to look at ways of monitoring/controlling the temperature (which was the subject of yet another previous blog and video) with the aim of baking SMD parts onto a PCB to maybe make a working programmer.
After testing the oven's capabilities, I opened up the stencil, scraped some solder paste onto a board and then spent a happy half hour carefully placing components onto the board.
The oven fired up and although it was clearly a bit "half-baked", the rig worked well and a few minutes later I had my first cooked PCB.
However, we have been here before and so it was with some trepidation that I loaded up the firmware, stuck in a padauk (PFS154) and firstly tried to recognise and then program the chip.
Success! And now we look at how to program these strange exotic beasts to do some useful work around the place instead of sucking up all my time!
I duly whipped up the clock according to his instructions, the only wrinkle being that the I2C based LED matrix modules needed to have solder bridges which result in a "hard wiring" of their I2C address.
On the breadboard the clock worked fine, so next up I decided to make a 3D printed fascia to fit the matrix modules plus a couple of switches.
Of course I forgot space for the battery, so the final design needed a couple of extra centimetres at the bottom to allow for a 18650 cell.
Next I used FreeCad and then Ultimaker Cura to first design and then slice the 3D model. I go into some detail for these processes in the video below.
The whole thing then needed some soldering and assembling and "voilĂ " we have a clock! I put some M3 bolts in the corners to stick to magnets and so it now sits on the fridge happily keeping time. I love the dissolve effect as it transitions from one minute to the next.
It's a bit battery hungry (a changed needed every 2 weeks or so), but considering I'm using cheap rechargeables at the moment it is not such an issue.
On my "to do" list is to further limit the brightness of the display as suggested by David on his original blog, plus modify the code to make a 24-hour version.
Note: it is the summer holidays DownUnder, so this blog (and YT channel) will be taking a little break for a month - see you in 2021!
Who doesn't love red and green flashing LEDs at Christmas? For the last couple of years we have had these little CR2032 driven ATTiny13 chips flashing a couple of 5mm LEDs strewn throughout the house (and outside).
The microcontrollers are running at 1MHz and they are mostly sleep, just pumping out alternate 1/8th second blips to the LEDs followed by a 4 second gap. In this guise the coin cells last around 6-9 months (!!), although they do get a bit dim towards the end of that run.
This year I decided to update the project, again using ATTiny13a chips, but this time ambling along at 128kHz (less power) which switch 1206 SMD LEDs (less power at 1/4W), but flashing more frequently (1/8th second on, 1/2 second off). So it will be very interesting to see how they last through the festive season and beyond. I can't remember if the original was coded in assembly or not, but this one sure is:
;
; Device: ATtiny13A, Package: 8-pin-PDIP_SOIC
;
; ______
; 1 / |8
; RESET o--| |--o VCC
; 2| |7
; PB3 o--| |--o PB2
; 3| |6
; PB4 o--| |--o PB1
; 4| |5
; GND o--| |--o PB0
; |_______|
;
.nolist
.include "tn13adef.inc" ; Define device ATtiny13A
.list
; **********************************
; R E G I S T E R S
; **********************************
.def rSreg = R15 ; Save/Restore status port
.def rmp = R16 ; Define multipurpose register
.def colour = R1
; **********************************
; S R A M
; **********************************
.dseg
.org SRAM_START
; **********************************
; C O D E
; **********************************
.cseg
.org 000000
; **********************************
; R E S E T & I N T - V E C T O R S
; **********************************
rjmp Main ; Reset vector
reti ; INT0
reti ; PCI0
reti ; OVF0
reti ; ERDY
reti ; ACI
reti ; OC0A
reti ; OC0B
rjmp mytimer_ISR ; watchdog timer interrupt
reti ; ADCC
; **********************************
; I N T - S E R V I C E R O U T .
; **********************************
; Add all interrupt service routines
mytimer_ISR:
; as I understand it, cli and sei are automatic on
; entry and exit respectively of ISR
in r16, SREG ; save SREG
push r16 ; do this if you want to use
finishisr:
pop r16 ; do this if you pushed SREG above
out SREG, r16 ; restore SREG
reti
; **********************************
; M A I N P R O G R A M I N I T
; **********************************
Main:
ldi rmp,Low(RAMEND)
out SPL,rmp ; Init LSB stack pointer
ldi r16, 0b00011000 ; output mode for PB3/4
out DDRB, r16
ldi r16, 0b00010000
mov colour, r16 ; red is on
; turn on PB4, enable internal pullups
; on the rest of the pins except PB3
ldi r16, 0b11110111
out PORTB, r16
; **********************************
; P R O G R A M L O O P
; **********************************
Loop:
rcall waitabit ; 1/16 second subroutine
rcall waitalot ; 1/2 second subroutine
rjmp Loop
waitabit:
wdr ; reset watchdog timer
ldi r16, 0b01000010 ; 1/8 second timer
out WDTCR, r16
rcall sleepnow ; sleep subroutine
rcall flipbit ; flip the led, if off then on, etc.
ret
waitalot:
wdr ; reset watchdog timer
ldi r16, 0b01000101 ; 1/2 second timer
out WDTCR, r16
rcall sleepnow ; sleep subroutine
rcall flipbit ; flip the leds
ret
sleepnow:
; sleep enable, power down mode
ldi r16, 0b00110000
out MCUCR, r16
; disable ADC
ldi r16, 0b00010000
out ADCSRA, r16
; disable interrupts to make sure the following
; timed sequence is not interrupted
cli
; disable BOD - must be done in a timed sequence
; as follows, write 1 to BODS and BODSE then within
; four clock cycles write 1 to BODS and 0 to BODSE
; then within three clock cycles enable sleep
; page 33 on the datasheet
ldi r16, 0b00000011
ldi r17, 0b00000010
out BODCR, r16
out BODCR, r17
sei
sleep
; sleep disable
ldi r16, 0b00000000
out MCUCR, r16
ret
flipbit:
in r16, pinb ; what is the state of the pins?
andi r16, 0b00011000 ; load red or green on
brbc 1, turnoff
testred:
mov r16, colour
ldi r17, 0b00001000
cp r16, r17
brbs 1, greenon
redon:
ldi r16, 0b00001000 ; set colour red
mov colour, r16 ; and make it so
ldi r16, 0b00001000
out portb, r16
rjmp finishflip
greenon:
ldi r16, 0b00010000 ; set colour green
mov colour, r16 ; and make it so
ldi r16, 0b00010000
out portb, r16
rjmp finishflip
turnoff:
ldi r16, 0b00000000
out portb, r16
finishflip:
ret
; End of source code
The only downside is that with the frantic flashing the place looks like an alien landing site or a Christmas super computer - good one!
In line with some other current projects, it is my solemn promise to make next year's batch from Pesky Padauk microcontrollers, probably the PMS150C.
There is an Orange Pi Zero attached to my 3D printer running OctoPrint as per a previous post and YouTube video. On the assumption that it might run hot at times (introducing the possibility of a throttle or shutdown scenario) I connected a fan to the top of the printed enclosure which runs continuously off the 5V rail.
The fan is a bit noisy, although that doesn't matter as the unit is located downstairs in the garage/workshop, but also I was thinking that it may not be necessary to have the fan running all of the time. Maybe it only needs to cut in and out as the temperature of the board changes?
While the Orange Pi Zero is working well with the printer at the moment I don't want to hassle it too much, so to test a few ideas kicking around in my noggin I grabbed an Orange Pi PC as a guinea pig instead.
I loaded an SD card with the appropriate version of Armbian (choosing the "focal" version). Included with the OS is the command "armbianmonitor -m" which can check the temperature of the SOC directly. You can also find out the temperature via the command:
"cat /sys/class/thermal/thermal_zone0/temp"
...which will output something like 29200 if the temperature is 29.2°C.
The first (and most recommended) method of temperature mitigation for this board is to attach a heat sink to the SOC, in this case an ARM H3+.
Without doing extensive tests, this one simple modification did lower the temperature quite a bit - and I'm pretty sure from reading a few of the forums posts out there that this would be sufficient to keep the board cool. The only thing is that if the board does start to overheat, then performance is throttled and perhaps a a long print run might end up being interrupted and/or stopped - very sad!
Therefore, I 3D-printed a suitable enclosure that allowed for a fan to be installed directly over the SOC.
The fan works directly from either the 5V or the 3.3V rail as per the Orange Pi Zero version, but here I wanted to dive a little deeper and control the fan according to need. After reading about many options, I found this site which recommended a GPIO linked to a transistor as a switching mechanism (I've altered the circuit to suit as shown below).
Then, by controlling the GPIO status (HIGH or LOW), it should be possible to turn on and off the fan as required. Although many sites recommended a python-based solution for the control of the pin, I chose a bash script instead as per this github repository because I plan to have the script run at start-up (perhaps as a daemon) and this solution seemed the most likely to succeed.
I had to modify the script a bit (to include for instance hysteresis and address some scripting errors), but it ended up being as follows:
Monitoring of the CPU showed the temperature shooting up, and then the fan coming on and keeping everything cool - only to turn off when the "stress" is off. Very good result!
The final part was to solder up a board with the extra bits including the transistor to be placed inside the cooled housing, and make all the connections as per the breadboard test.
Now all I need to do is to retrofit this solution to the Orange Pi Zero attached to the printer and that will be mission accomplished!
I was musing about two recent but separate projects, one which sings the praises of the QX5252 chip and the other which throws the ATTiny13 chip into a watchdog role. What if the watchdog could effectively haveendless energy via the big yellow in the sky, and so can run "forever" and be available to do watchdog-type activities?
I decided to test the addition of a second QX5252, one chip operating to "pump" out stable energy to the microcontroller, and the other to grab ergs from the sun when available.
Normally with the QX5252 and similar ICs the chip shuts down the output of the circuit if there is enough light, and all of the solar panel energy is shunted to the rechargeable battery for the next night of LED fun. If, however, you want the battery to simultaneously charge and discharge during the day (is that even possible?) then one variation worth exploring is to maybe employ a second QX5252 just for that purpose.
So the plan is:
use the "normal" stable joule thief PCB and program an ATTiny13 to do something (probably blink), but do not connect a Solar Panel to the board so that the QX5252 is fooled into being always in "discharge" mode
add another QX5252 to the rail, but have no output components such that it is charging the battery if there is any light available to do so
In part (1), above, I struggled to write the assembly code which initially seemed an easy variation on previous projects. All I wanted to do was use two LEDs and flash them alternatively for 2 seconds on then 8 seconds off - e.g. red on (2 seconds), all off (8 seconds), yellow on (2 seconds), all off (8 seconds), rinse and repeat...
Of course, if the states of the LEDs are not changing then the microcontroller can sleep to save power. Also the little fella should be running anaemically at 128kHz thus drawing minimum current.
Eventually the code worked, but if you can see a better way to more efficiently and/or clearly write these routines, please leave a comment on the YouTube channel.
.nolist
.include "tn13adef.inc" ; Define device ATtiny13A
.list
; **********************************
; H A R D W A R E
; **********************************
; Device: ATtiny13A, Package: 8 - pin - PDIP_SOIC
;
; ____________
; 1 / | 8
; o-- | RESET VCC | --o
; o-- | PB3 PB2 | --o
; o-- | PB4 PB1 | --o
; o-- | GND PB0 | --o
; 4 |____________| 5
;
; **********************************
; C O D E
; **********************************
.cseg
.org 000000
; **********************************
; R E S E T & I N T - V E C T O R S
; **********************************
rjmp Main ; Reset vector
reti ; INT0
reti ; PCI0
reti ; OVF0
reti ; ERDY
reti ; ACI
reti ; OC0A
reti ; OC0B
rjmp mytimer_ISR ; my interrupt
reti ; ADCC
; **********************************
; I N T - S E R V I C E R O U T .
; **********************************
mytimer_ISR:
; sleep is interrupted, program returns
reti
; **********************************
; M A I N P R O G R A M I N I T
; **********************************
;
Main:
ldi r16, Low(RAMEND)
out SPL, r16 ; Init LSB stack pointer
; output mode for PB3, PB4, input for the rest
ldi r16, 0b00011000
out DDRB, r16
; turn on PB4, enable internal pullups
; on the rest unused pins
ldi r16, 0b11110111
out PORTB, r16
; which LED is active?
ldi r18, 0b00010000 ; start with PB4
; **********************************
; P R O G R A M L O O P
; **********************************
Loop:
rcall waitabit ; 2 second (on)
rcall waitalot ; 8 seconds (off)
rjmp loop
waitabit:
; reset watchdog timer
wdr
; 2 second timer
ldi r16, 0b01000111 ; see datasheet
out WDTCR, r16
rcall sleepnow
rcall flipbit
ret
waitalot:
; reset watchdog timer
wdr
; 8 second timer
ldi r16, 0b01100001 ; see datasheet
out WDTCR, r16
rcall sleepnow
rcall flipbit
ret
sleepnow:
; see datasheet MCUCR, ADCSRA, BODCR
; sleep enable, power down mode
ldi r16, 0b00110000
out MCUCR, r16
; disable ADC
ldi r16, 0b00010000
out ADCSRA, r16
; disable interrupts to make sure the following
; timed sequence is not interrupted
cli
; disable BOD - must be done in a timed sequence
; as follows, write 1 to BODS and BODSE then within
; four clock cycles write 1 to BODS and 0 to BODSE
; then within three clock cycles enable sleep
; page 33 on the datasheet
ldi r16, 0b00000011
ldi r17, 0b00000010
out BODCR, r16
out BODCR, r17
sei
sleep
; sleep disable
ldi r16, 0b00000000
out MCUCR, r16
ret
flipbit:
cpi r18, 0b00010000 ; is pb4 active?
brbs 1, workonpb4
workonpb3:
in r16, portb
andi r16, 0b00001000 ; mask all but PB3
cpi r16, 0b00001000 ; is pb3 on?
brbs 1, turnoffpb3
in r16, portb ; flip PB3
ldi r17, 0b00001000
eor r16, r17
out portb, r16
rjmp finishflip
turnoffpb3:
in r16, portb ; flip PB3
ldi r17, 0b00001000
eor r16, r17
out portb, r16
ldi r18, 0b00010000 ; make PB4 active
rjmp finishflip
workonpb4:
in r16, portb
andi r16, 0b00010000
cpi r16, 0b00010000 ; is PB4 on?
brbs 1, turnoffpb4
in r16, portb ; flip PB4
ldi r17, 0b00010000
eor r16, r17
out portb, r16
rjmp finishflip
turnoffpb4:
in r16, portb ; flip PB4
ldi r17, 0b00010000
eor r16, r17
out portb, r16
ldi r18, 0b00001000 ; make PB3 active
finishflip:
ret
; End of source code
I was very stoked to see this circuit and code not only work as intended, but also hold its own over weeks of testing, oscillating between about 1.33V after a day of sunshine to 1.25V after a couple of days and nights of overcast misery. Nice one two QX5252 Frankenstein bloke!
The only question remaining is: should I add a couple of diodes going to the rail from each of the outputs so they don't interfere with each other? Are the losses so great (although they would probably be Schottky diodes for minimum forward voltage) that it's not worth the addition? There are more tests to be made, but for now enjoy the <usual> blinking madness.