OK, het heeft wat tijd gekost maar het is me gelukt (met wat hulp van Koffie) om een op attiny85 gebaseerde KaKu-compatibele zender te maken!
Omdat ik me kan voorstellen dat meer mensen dit interessant vinden zal ik proberen het proces hieronder te beschrijven.
Eerst wat feitjes:
- deze zender is in feite een vervanger van de AWMT-003 van KaKu. Je kan hem dus aansluiten op een bestaande lichtschakelaar, waar de zender dan op reageert. Nooit 220V hierop aansluiten!
- Kosten: minder dan 5 euro per unit ;-) (als je arbeidsloon op 0 zet).
Benodigdheden
- RF transmitter. Ik heb er nu 1 gebruikt van een superheterodyne-ontvanger setje, maar via ebay zijn ze voor ongeveer 1 USD per stuk te koop. Als ik meer ervaringen heb zal ik die posten
- Attiny85
- Breadboard, of experimenteerplaat en een soldeerbout
- USB AVR programmer (USBASP is prima, kan je voor 6 euro kopen met snelle verzendtijd in NL)
- Tijd (hoewel het idee van deze tutorial is dat je het binnen een uur lopend zou moeten hebben)
Voorbereiding
- Download en installer Arduino IDE
Reboot windows met de optie om unsigned drivers te installeren (
http://forums.laptopvideo...ned-drivers-in-windows-8/)
- Fix installeren :
http://forum.arduino.cc/index.php/topic,116674.0.html
- Attiny files installeren (
http://highlowtech.org/?p=1695 ->
https://github.com/damellis/attiny/archive/master.zip )
Testen
- Sluit de attiny85 op de goede manier aan op de USBASP programmer.
De pinout van de attiny85 is hier te vinden

De standaard pinout van de usbasp is ook makkelijk te vinden.
Sluit een led aan op pin 0 van de attiny85, en de andere kant via een weerstand naar de GND
Arduino IDE starten
Juiste board selecteren, juiste programmer selecteren
Selecteer in de IDE via file-example-basics bijvoorbeeld blink of fade en verander in die code de 13 door een 0.
Vervolgens uploaden, en met een beetje gelukt werkt het in een keer. Deze foutmelding is normaal:
code:
1
| avrdude: warning: cannot set sck period. please check for usbasp firmware update. |
Als het een nieuwe attiny is zal de knipperfrequentie erg traag zijn. Zet hem daarom op 8MHz (ook nodig voor het zenden van 433Mhz code) en Burn Bootloader (via tools menu). Dan zal het beter gaan. Dit moet dus altijd bij een nieuwe chip.
Het echte werk
Eigenlijk is het heel simpel. Sluit de Attiny en de transmitter aan op 5V en GND, de datapin van de transmitter op een van de pins van de Attiny.
Om de knop te laten werken moet je 1 kant aansluiten aan de GND en de ander aan een van de ongebruikte pins van de Attiny (of 2x als je een dubbele knop hebt).
Voor eens simpele aan-uit knop kan je deze code gebruiken. De data uitgang van de transmitter gaat aan pin0, en de knoppen aan pin3 en pin4.
De code lijkt me vrij vanzelfsprekend. Tussendoor slaapt de attiny, dat verlengt het leven van de batterijen nogal.
code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
| #include <avr/sleep.h> // Sleep Modes
#include <avr/power.h>
#include <NewRemoteTransmitter.h>
const int txPin = 0;
NewRemoteTransmitter transmitter(111, txPin, 260, 2);
NewRemoteTransmitter transmitter2(112, txPin, 260, 2);
const byte SWITCH = 3;
const byte SWITCH2 = 4;
int buttonState = 1; // variable for reading the pushbutton status
int buttonLast = 1;
int buttonState2 = 1; // variable for reading the pushbutton status
int buttonLast2 = 1;
int notimesmax = 10;
ISR (PCINT0_vect)
{
// do something interesting here
}
void setup ()
{
pinMode (SWITCH, INPUT);
pinMode (SWITCH2, INPUT);
pinMode(txPin, OUTPUT); // RF TRANSMITTER
digitalWrite (SWITCH, HIGH); // internal pull-up
digitalWrite (SWITCH2, HIGH); // internal pull-up
// pin change interrupt (example for D4)
PCMSK |= bit (PCINT3);
PCMSK |= bit (PCINT4);
GIFR |= bit (PCIF); // clear any outstanding interrupts
GIMSK |= bit (PCIE); // enable pin change interrupts
} // end of setup
void loop ()
{
delay (100);
for(int notimes = 0;notimes<notimesmax;notimes++){//Loop to prevent errors when hitting the 2 buttons simultaneously
buttonState = digitalRead(SWITCH);
buttonState2 = digitalRead(SWITCH2);
if (buttonState != buttonLast) {
if(buttonState == HIGH) transmitter.sendUnit(0, true);
if(buttonState == LOW) transmitter.sendUnit(0, false);
buttonLast = buttonState;
}
if (buttonState2 != buttonLast2) {
if(buttonState2 == HIGH) transmitter2.sendUnit(0, true);
if(buttonState2 == LOW) transmitter2.sendUnit(0, false);
buttonLast2 = buttonState2;
}
}
} // end of loop
void goToSleep ()
{
set_sleep_mode(SLEEP_MODE_PWR_DOWN);
ADCSRA = 0; // turn off ADC
power_all_disable (); // power off ADC, Timer 0 and 1, serial interface
sleep_enable();
sleep_cpu();
sleep_disable();
power_all_enable(); // power everything back on
} // end of goToSleep |
Als je iets ingewikkelders wilt, bijvoorbeeld met dimmers, dan kan dat ook natuurlijk. Idee is dat als je 2x vrij snel na elkaar drukt, dat er dan een dimmermodus optreedt waar je uitkomt door nog een keer op de knop te drukken.
Code heb ik nog niet getest met een zender, alleen met ledjes, dus is onder voorbehoud. Ik zal deze post updaten met nieuwe code. Er zit wat code in die te maken heeft met het feit dat ik 'correcties' wilt laten uitvoeren door pimatic (als je een lamp aan zet die al aan staat dan moet-ie uit). Dat ga ik nog wat verder testen, als het goed werkt dan post ik daar wel wat over.
code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
| #include <avr/sleep.h> // Sleep Modes
#include <avr/power.h>
#include <NewRemoteTransmitter.h>
const int txPin = 0;
const int LED = 2;
NewRemoteTransmitter transmitter(111, txPin, 260, 2);
NewRemoteTransmitter transmitter2(112, txPin, 260, 2);
NewRemoteTransmitter transmitter3(1011, txPin, 260, 3);
NewRemoteTransmitter transmitter4(1021, txPin, 260, 3);
//const byte LED = 4; // pin 2
const byte SWITCH = 3; // pin 3 / PCINT4
const byte SWITCH2 = 4; // pin 3 / PCINT4
int buttonState = 1; // variable for reading the pushbutton status
int buttonLast = 1;
int buttonState2 = 1; // variable for reading the pushbutton status
int buttonLast2 = 1;
int notimesmax = 10;
int switched1 = 0;
int switched2 = 0;
int dimlevel = 15;
int dimlevel2 = 15;
int startdimlevel = 15;
int lastsignal = 1;
int lastsignal2 = 1;
ISR (PCINT0_vect)
{
// do something interesting here
}
void setup ()
{
pinMode (SWITCH, INPUT);
pinMode (SWITCH2, INPUT);
pinMode(txPin, OUTPUT); // RF TRANSMITTER
digitalWrite (SWITCH, HIGH); // internal pull-up
digitalWrite (SWITCH2, HIGH); // internal pull-up
// pin change interrupt (example for D4)
PCMSK |= bit (PCINT3); // want pin D4 / pin 3
PCMSK |= bit (PCINT4); // want pin D4 / pin 3
GIFR |= bit (PCIF); // clear any outstanding interrupts
GIMSK |= bit (PCIE); // enable pin change interrupts
} // end of setup
void loop ()
{
for(int notimes = 0;notimes<notimesmax;notimes++){
digitalWrite (LED, HIGH);
delay (10);
digitalWrite (LED, LOW);
delay (10);
buttonState = digitalRead(SWITCH);
buttonState2 = digitalRead(SWITCH2);
if (buttonState != buttonLast & switched1 == 0) {
if(lastsignal == 0) {
transmitter.sendUnit(0, true);
lastsignal = 1;
}
if(lastsignal == 1){
transmitter.sendUnit(0, false);
lastsignal = 0;
}
switched1 = 1;
buttonLast = buttonState;
}
if (buttonState2 != buttonLast2 & switched2 == 0) {
if(lastsignal2 == 0) {
transmitter2.sendUnit(0, true);
lastsignal2 = 1;
}
if(lastsignal2 == 1){
transmitter2.sendUnit(0, false);
lastsignal2 = 0;
}
// digitalWrite (LED, HIGH);
// delay(500);
// digitalWrite (LED, LOW);
// delay(500);
switched2 = 1;
buttonLast2 = buttonState2;
}
if (buttonState != buttonLast & switched1 == 1) {
if(lastsignal == 0) transmitter.sendUnit(0, true);
while (buttonState != buttonLast) { //Button was hit again, time to go into the dimmer mode until button is hit again
dimlevel = dimlevel - 1;
if (dimlevel<0) dimlevel = startdimlevel;
transmitter.sendDim(0, dimlevel);
buttonState = digitalRead(SWITCH);
lastsignal = 1;
}
transmitter3.sendUnit(0, true);
buttonLast = buttonState;
dimlevel = startdimlevel;
}
if (buttonState2 != buttonLast2 & switched2 == 1) {
if(lastsignal == 0) transmitter2.sendUnit(0, true);
while (buttonState2 != buttonLast2) { //Button was hit again, time to go into the dimmer mode until button is hit again
dimlevel2 = dimlevel2 - 1;
if (dimlevel2<0) dimlevel2 = startdimlevel;
transmitter2.sendDim(0, dimlevel);
buttonState2 = digitalRead(SWITCH2);
lastsignal2 = 1;
}
transmitter4.sendUnit(0, true);
buttonLast2 = buttonState2;
dimlevel2 = startdimlevel;
}
}
// notimes = notimes +1;
// if(notimes>notimesmax)
goToSleep ();
} // end of loop
void goToSleep ()
{
set_sleep_mode(SLEEP_MODE_PWR_DOWN);
ADCSRA = 0; // turn off ADC
power_all_disable (); // power off ADC, Timer 0 and 1, serial interface
sleep_enable();
sleep_cpu();
sleep_disable();
power_all_enable(); // power everything back on
switched1 = 0;
switched2 = 0;
// notimes = 1;
} // end of goToSleep |
En hoe ziet het er dan uit
Je kan de zender en attiny koppelen aan 2 of 3 AAA batterijen. In mijn 4cm diepe wanddozen kan ik net een 3AAA-batterijenhouder kwijt + zender + transmitter.
Ik heb het stroomverbruik gemeten en kom dan uit op een geschatte levensduur van 3 900mAH batterijen van 1200 dagen. Waarschijnlijk loopt de batterij sneller leeg, maar in elk geval moet dat genoeg zijn zou ik zeggen.
Plaatje van de printlayout (op experimenteerprint)

Rood=3 of 5V, Zwart is GND (1 voor de stroombron en 1 voor de lichtknop) en die andere zijn voor de lichtknop.
Resultaat: