Tack Micke! Jag fick inte till rätt URL själv, med din URL gick det bra.
Utan att ha läst hela koden hade jag svårt att tolka bara "Rising Sun"-delen av ert program, och det var inte så svårt att koppla min Saleae Logic logikanalysator till en mottagarmodul från K&Co och ta reda på vad som sändes för de olika tillstånden. Tillsammans med
specifikationen på Domia Lite-protokollet var det inte svårt att skriva ett enkelt program som styr just dessa budget-strömbrytare från K&Co. (Arduino-kod längre ned i texten.)
Modulerna jag använder är antagligen från Welleman, och mottagarmodulen verkar ha "AGC", "automatic gain control", så när den inte får någon tydlig signal ökar den känsligheten och börjar ta emot allmänt brus istället, vilket gjorde det svårt att säkert se vad som var den signal jag letade efter och vad som var brus. Jag slängde snabbt ihop ett Arduino-program som sände logisk etta (alltså aktiv signal) i 25 ms och logisk nolla (ingen sändning(?)) i 110 ms. Denna signal dränkte signalen från fjärrkontrollen (och temperatur-sensorn) när den sände logisk etta, men det gav mig en uppfattning om vad jag skulle leta efter i bruset, hur långa de olika delsignalerna skulle vara etc. Just med strömbrytarnas fjärrkontroll gick det också bra att hålla ned en knapp under hela registreringen för att bara få med detta, men det var värre när jag skulle försöka ta emot temperatur-sensorerna till den trådlösa utomhustermometern eftersom den bara sänder en gång per minut.
Förutom att jag nu kan styra Rising Sun-brytarna så har jag ett par exempel (23,9 och 24,0 grader, en av tre möjliga sensorer aktiv) på sändning från en temperatur-sensor, men jag har inte försökt analysera det protokollet ännu.
Rising Sun använder en enklare variant av Domia Lite-protokollet, kanske liknande äldre Nexa-enheter. Mitt kodexempel använder de faktiska tider som fjärrkontrollen använder, istället för de tider som Domia-specen anger (jag använder 1700 ms per bit istf 1500 ms). Protokollet använder fyra bitar per adress, två adressgrupper (hus/grupp och individ/enhet), men har bara stöd för fyra faktiska adresser per adressenhet. Adressen är alltså 1-4, och den bit som (från vänster) motsvarar adressen är en logisk nolla, rester är logisk etta. Adress två sänds alltså som 0100. Tredje fyrabitarsgruppen styr av/på, och där är det sista biten som avgör, på är 1111, av är 1110.
En 0-bit består av hög signal 1/4 av bit-tiden (här 425 µs), låg signal 3/4 av bit-tiden (här 1275 µs). En 1-bit består av hög signal 3/4 av tiden, låg signal 1/4 av tiden. Varje överföring av en faktisk bit består av en 0- eller 1-bit följt av en 0-bit, så de tolv logiska bitarna kommer att bli 24 fysiska bitar, och hela meddelandet inleds med en fysisk 0-bit. Detta 25-bitars meddelande upprepas med (i mitt fall) 13 ms mellanrum. Någon preamble för att väcka och synka mottagaren förekommer inte, istället upprepas meddelandet flera gånger (fem gånger har fungerat bra för mig).
Vill jag t ex slå på enhet två i grupp fyra (som i mitt programexempel) vill jag överföra de logiska bitarna 1110 1011 1111, och för att slå av samma enhet 1110 1011 1110. Tillsammans med de 0-bitar som används blir hela meddelandet som skickas till sändaren 0 10101000 10001010 10101010 respektive 0 10101000 10001010 10101000.
Den som inte använder Arduino kan se följande kod som pseudo-kod, jag tror att det skall vara ganska enkelt att förstå och anpassa till fristående AVR, PIC eller vad som helst. (I/O-pinne 13 är kopplad till en LED på Arduino-kortet som här kommer att lysa när strömbrytaren skall vara på.)
Kod: Markera allt
#define txPin 7
#define period 1700
#define delayShort (period / 4)
#define delayLong ((period * 3) / 4)
unsigned int rfDelay[2][2] = { {delayShort, delayLong}, {delayLong, delayShort} };
void txBitRaw(byte rfBit) {
digitalWrite(txPin, HIGH);
delayMicroseconds(rfDelay[rfBit][0]);
digitalWrite(txPin, LOW);
delayMicroseconds(rfDelay[rfBit][1]);
}
void txBit(byte rfBit) { // rfBit = {0, 1}
txBitRaw(rfBit);
txBitRaw(0);
}
void txAddr(byte rfAddr) { // rfAddr = {1-4}
for(int i=1; i<=4; i++) {
if(i == rfAddr) {
txBit(0);
} else {
txBit(1);
}
}
}
void txState(byte rfState) { // rfState = {0, 1}
for(int i=0; i<3; i++) {
txBit(1);
}
txBit(rfState);
}
void txSwitch(byte rfAddr1, byte rfAddr2, byte rfState) {
for(int i=0; i<5; i++) {
delay(13); // milliseconds
txBitRaw(0);
txAddr(rfAddr1); // major address
txAddr(rfAddr2); // minor address
txState(rfState); // on/off
}
}
void setup() {
pinMode(txPin, OUTPUT);
pinMode(13, OUTPUT);
}
void loop() {
for(;;) {
digitalWrite(13,HIGH);
txSwitch(4,2,1);
delay(5000);
digitalWrite(13,LOW);
txSwitch(4,2,0);
delay(5000);
}
}
Programmet är skrivet för att testa att konceptet fungerar, så inga funktioner kollar efter felaktiga parametrar.
Jag kan förresten nämna att ungefär när jag började labba med detta fick jag grejerna jag beställt från
Seeedstudio, och när jag kollade lite mer på deras sidor hittade jag likvärdiga sändar-/mottagarmoduler för $4.31 per kit med en sändare och en mottagare, och de har också ett kit som uppges klara upp till 2 km räckvidd.
Själv är jag nyfiken på att testa med bättre antenner, kanske en enkel dipol utformad efter faktisk våglängd och med korrekt jordplan, kanske en enkel yagi-udo eller annan riktantenn, men jag vet inte om den lilla sändarmodulen (som jag då lär mata med max rekommenderade 12V) blir för varm då. Blir den det får jag väl försöka kyla den på något vettigt sätt, eller försöka designa en själv som klarar högre uteffekt.