ansluta-control/ansluta arduino code/ansluta.ino

459 lines
15 KiB
C++

/*
Ansulta Control with NodeMCU and CC2500
created 24.11.2018
by matlen67
Hardware:
* NodeMCU Lolin V3 (az-delivery)
* CC2500 (WLC240) (ebay)
Wired:
NodeMCU CC2500
SPI GPIO Board
---------------------- --------
SLC GPIO14 (D5) SCLK
MISO GPIO12 (D6) MISO
MOSI GPIO13 (D7) MOSI
CSx GPIO15 (D8) CSN
*/
#include "cc2500_REG.h"
#include "cc2500_VAL.h"
#include "cc2500_CMD.h"
#include <SPI.h>
#include <ESP8266WiFi.h>
#define CS 15 // ChipSelect NodeMCU Pin15
#define Light_OFF 0x01 // Command to turn the light off
#define Light_ON_50 0x02 // Command to turn the light on 50%
#define Light_ON_100 0x03 // Command to turn the light on 100%
#define Light_PAIR 0xFF // Command to pair a remote to the light
const boolean DEBUG = false; // debug mode print same infos by RS232
const char* ssid = "here your SSID";
const char* password = "here your Wlankey";
WiFiServer server(80);
String header;
/* get your ansluta address!
-------------------------
connect browser to webcontrol
example: 192.168.178.130/ansluta/getAddress
press button within 5 sec on your original ansluta remote
is a valid address detect it will be displayed
*/
// pute here your AddressBytes
byte AddressByteA = 0xD0;
byte AddressByteB = 0x9A;
void setup(){
// config ChipSelect
pinMode(CS,OUTPUT);
if(DEBUG){
Serial.begin(115200);
Serial.println("Debug mode");
Serial.print("Initialisation");
}
// Connect to Wi-Fi network with SSID and password
if(DEBUG){
Serial.print("Connecting to ");
Serial.println(ssid);
}
WiFi.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED) {
delay(500);
if(DEBUG){
Serial.print(".");
}
}
// Print local IP address and start web server
if(DEBUG){
Serial.println("");
Serial.println("WiFi connected.");
Serial.println("IP address: ");
Serial.println(WiFi.localIP());
}
server.begin();
// SPI config
SPI.begin();
SPI.setDataMode(SPI_MODE0);
SPI.setBitOrder(MSBFIRST);
SPI.setClockDivider(SPI_CLOCK_DIV64);
digitalWrite(CS,HIGH);
SendStrobe(CC2500_SRES); //0x30 SRES Reset chip.
init_CC2500();
// SendStrobe(CC2500_SPWD); //Enter power down mode - Not used in the prototype
WriteReg(0x3E,0xFF); //Maximum transmit power - write 0xFF to 0x3E (PATABLE)
if(DEBUG){
Serial.println(" - Done");
}
// end setup
}
void loop(){
WiFiClient client = server.available(); // Listen for incoming clients
if (client) { // If a new client connects,
if(DEBUG){
Serial.println("New Client."); // print a message out in the serial port
}
String currentLine = ""; // make a String to hold incoming data from the client
String adrByte = "";
boolean adrState = false;
int timeOut = 0;
while (client.connected()) { // loop while the client's connected
timeOut ++;
if (timeOut >= 500000){ // dirty workaround because ClientTimeout not Work!
client.stop(); // Chrome keep alive the connection and block other connection (Fhem,Firefox)
}
if (client.available()) { // if there's bytes to read from the client,
char c = client.read(); // read a byte, then
if(DEBUG){
Serial.write(c); // print it out the serial monitor
}
header += c;
if (c == '\n') { // if the byte is a newline character
// if the current line is blank, you got two newline characters in a row.
// that's the end of the client HTTP request, so send a response:
if (currentLine.length() == 0) {
// HTTP headers always start with a response code (e.g. HTTP/1.1 200 OK)
// and a content-type so the client knows what's coming, then a blank line:
client.println("HTTP/1.1 200 OK");
client.println("Content-type:text/html");
client.println("Connection: close");
client.println();
// Display the HTML web page
client.println("<!DOCTYPE html><html>");
client.println("<head><meta name=\"viewport\" content=\"width=device-width, initial-scale=1\">");
client.println("<link rel=\"icon\" href=\"data:,\">");
// CSS to style the on/off buttons
// Feel free to change the background-color and font-size attributes to fit your preferences
client.println("<style>html { font-family: Helvetica; display: inline-block; margin: 0px auto; text-align: center;}");
client.println(".button { width: 10em; margin-left: auto; margin-right: auto; background-color: #195B6A; border: solid 1px transparent;border-radius: 4px; color: white; padding: 16px 40px;");
client.println("text-decoration: none; font-size: 30px; margin: 2px; cursor: pointer;}");
client.println(".button2 {background-color: #77878A;}</style></head>");
// Web Page Heading
client.println("<body><h1>-- NodeMCU --</h1>");
client.println("<body><h2>Ansluta Control</h2>");
// turn the light on/off
if (header.indexOf("GET /ansluta/50") >= 0) {
if(DEBUG){
Serial.println("Ansluta 50% ");
}
SendCommand(AddressByteA,AddressByteB, Light_ON_50);
} else if (header.indexOf("GET /ansluta/100") >= 0) {
if(DEBUG){
Serial.println("Ansluta 100%");
}
SendCommand(AddressByteA,AddressByteB, Light_ON_100);
} else if (header.indexOf("GET /ansluta/0") >= 0) {
if(DEBUG){
Serial.println("Ansluta 0%");
}
SendCommand(AddressByteA,AddressByteB, Light_OFF);
} else if (header.indexOf("GET /ansluta/getAddress") >= 0) {
if(DEBUG){
Serial.println("Ansluta getAddress");
}
adrState = true;
client.println("<br>");
client.println("<p>Listen for adressbyte...</p>");
client.println("<p>Press button on original remote!</p>");
//client.println("</body></html>");
client.println();
delay(10);
client.flush();
//client.stop();
adrByte = ReadAddressBytes();
}
if(adrState == false){
client.println("<br>");
client.println("<p></p>");
client.println("<p><a href=\"/ansluta/50\"><button class=\"button\"> 50% </button></a></p>");
client.println("<br>");
client.println("<p></p>");
client.println("<p><a href=\"/ansluta/100\"><button class=\"button\">100%</button></a></p>");
client.println("<br>");
client.println("<p></p>");
client.println("<p><a href=\"/ansluta/0\"><button class=\"button\">off</button></a></p>");
}else{
client.println("<br>");
client.println("<p>Your Ansluta address: " + adrByte + "</p>");
adrState = false;
adrByte = "";
}
client.println("</body></html>");
// The HTTP response ends with another blank line
client.println();
// Break out of the while loop
break;
} else { // if you got a newline, then clear currentLine
currentLine = "";
}
} else if (c != '\r') { // if you got anything else but a carriage return character,
currentLine += c; // add it to the end of the currentLine
}
}
}
// Clear the header variable
header = "";
// Close the connection
//delay(1);
client.stop();
if(DEBUG){
Serial.println("Client disconnected.");
Serial.println("");
}
}
}
String ReadAddressBytes(){ //Read Address Bytes From a remote by sniffing its packets wireless
byte tries=0;
boolean AddressFound = false;
String A = "";
String B = "";
if(DEBUG){
Serial.print("Listening for an Address");
}
while((tries<200)&&(!AddressFound)){
SendStrobe(CC2500_SRX); // 0x34 Enable RX.
WriteReg(REG_IOCFG1,0x01); // REG_IOCFG1 = 0x01 Switch MISO to output if a packet has been received or not
delay(20);
byte PacketLength = ReadReg(CC2500_FIFO);
byte recvPacket[PacketLength];
if ( PacketLength >= 1) {
if(DEBUG){
Serial.println();
Serial.print("Packet received: ");
Serial.print(PacketLength,DEC);
Serial.println(" bytes");
}
if(PacketLength <= 8) { //A packet from the remote cant be longer than 8 bytes
for(byte i = 1; i <= PacketLength; i++){ //Read the received data from CC2500
recvPacket[i] = ReadReg(CC2500_FIFO);
if(DEBUG){
if(recvPacket[i]<0x10){Serial.print("0");}
Serial.print(recvPacket[i],HEX);
}
}
if(DEBUG){
Serial.println();
}
}
byte start=0;
while((recvPacket[start]!=0x55) && (start < PacketLength)){ //Search for the start of the sequence
start++;
}
if(recvPacket[start+1]==0x01 && recvPacket[start+5]==0xAA){ //If the bytes match an Ikea remote sequence
AddressFound = true;
AddressByteA = recvPacket[start+2]; // Extract the addressbytes
AddressByteB = recvPacket[start+3];
if(DEBUG){
Serial.print("Address Bytes found: ");
if(AddressByteA<0x10){Serial.print("0");}
Serial.print(AddressByteA,HEX);
if(AddressByteB<0x10){Serial.print("0");}
Serial.println(AddressByteB,HEX);
}
if(AddressByteA<0x10){A = "0";}
A += String(AddressByteA,HEX);
if(AddressByteA<0x10){B = "0";}
B += String(AddressByteB,HEX);
return A + B;
}
SendStrobe(CC2500_SIDLE); // Exit RX / TX
SendStrobe(CC2500_SFRX); // Flush the RX FIFO buffer
}
tries++;
}
if(DEBUG){
Serial.println(" - Done");
}
return "";
}
byte ReadReg(byte addr){
addr = addr + 0x80; // set r/w bit (bit7=1 read, bit7=0 write)
digitalWrite(CS,LOW);
delayMicroseconds(1); // can't wait for digitalRead(MISO)==HIGH! Don't work in SPI mode
byte x = SPI.transfer(addr);
delay(10);
byte y = SPI.transfer(0);
delayMicroseconds(1);
digitalWrite(CS,HIGH);
return y;
}
void SendStrobe(byte strobe){
digitalWrite(CS,LOW);
delayMicroseconds(1); // can't wait for digitalRead(MISO)==HIGH! Don't work in SPI mode
SPI.write(strobe);
digitalWrite(CS,HIGH);
delayMicroseconds(2);
}
void SendCommand(byte AddressByteA, byte AddressByteB, byte Command){
for(byte i=0;i<50;i++){ //Send 50 times
SendStrobe(CC2500_SFTX); // 0x3B
SendStrobe(CC2500_SIDLE); // 0x36
digitalWrite(CS,LOW);
delayMicroseconds(1); // can't wait for digitalRead(MISO)==HIGH! Don't work in SPI mode
SPI.transfer(0x7F); // activate burst data
delayMicroseconds(2);
SPI.transfer(0x06); // send 6 data bytes
delayMicroseconds(2);
SPI.transfer(0x55); // ansluta data byte 1
delayMicroseconds(2);
SPI.transfer(0x01); // ansluta data byte 2
delayMicroseconds(2);
SPI.transfer(AddressByteA); // ansluta data address byte A
delayMicroseconds(2);
SPI.transfer(AddressByteB); // ansluta data address byte B
delayMicroseconds(2);
SPI.transfer(Command); // ansluta data command 0x01=Light OFF 0x02=50% 0x03=100% 0xFF=Pairing
delayMicroseconds(2);
SPI.transfer(0xAA); // ansluta data byte 6
delayMicroseconds(2);
digitalWrite(CS,HIGH); // end transfer
SendStrobe(CC2500_STX); // 0x35 transmit data in TX
delayMicroseconds(1600);
}
//delay(20);
//SendStrobe(CC2500_SPWD); // 0x39 cc2500 sleep
//delayMicroseconds(2);
}
void WriteReg(byte addr, byte value){
digitalWrite(CS,LOW);
delayMicroseconds(1); // can't wait for digitalRead(MISO)==HIGH! Don't work in SPI mode
SPI.transfer(addr);
delayMicroseconds(1);
SPI.transfer(value);
delayMicroseconds(1);
digitalWrite(CS,HIGH);
}
void init_CC2500(){
WriteReg(REG_IOCFG2,VAL_IOCFG2);
WriteReg(REG_IOCFG0,VAL_IOCFG0);
WriteReg(REG_PKTLEN,VAL_PKTLEN);
WriteReg(REG_PKTCTRL1,VAL_PKTCTRL1);
WriteReg(REG_PKTCTRL0,VAL_PKTCTRL0);
WriteReg(REG_ADDR,VAL_ADDR);
WriteReg(REG_CHANNR,VAL_CHANNR);
WriteReg(REG_FSCTRL1,VAL_FSCTRL1);
WriteReg(REG_FSCTRL0,VAL_FSCTRL0);
WriteReg(REG_FREQ2,VAL_FREQ2);
WriteReg(REG_FREQ1,VAL_FREQ1);
WriteReg(REG_FREQ0,VAL_FREQ0);
WriteReg(REG_MDMCFG4,VAL_MDMCFG4);
WriteReg(REG_MDMCFG3,VAL_MDMCFG3);
WriteReg(REG_MDMCFG2,VAL_MDMCFG2);
WriteReg(REG_MDMCFG1,VAL_MDMCFG1);
WriteReg(REG_MDMCFG0,VAL_MDMCFG0);
WriteReg(REG_DEVIATN,VAL_DEVIATN);
WriteReg(REG_MCSM2,VAL_MCSM2);
WriteReg(REG_MCSM1,VAL_MCSM1);
WriteReg(REG_MCSM0,VAL_MCSM0);
WriteReg(REG_FOCCFG,VAL_FOCCFG);
WriteReg(REG_BSCFG,VAL_BSCFG);
WriteReg(REG_AGCCTRL2,VAL_AGCCTRL2);
WriteReg(REG_AGCCTRL1,VAL_AGCCTRL1);
WriteReg(REG_AGCCTRL0,VAL_AGCCTRL0);
WriteReg(REG_WOREVT1,VAL_WOREVT1);
WriteReg(REG_WOREVT0,VAL_WOREVT0);
WriteReg(REG_WORCTRL,VAL_WORCTRL);
WriteReg(REG_FREND1,VAL_FREND1);
WriteReg(REG_FREND0,VAL_FREND0);
WriteReg(REG_FSCAL3,VAL_FSCAL3);
WriteReg(REG_FSCAL2,VAL_FSCAL2);
WriteReg(REG_FSCAL1,VAL_FSCAL1);
WriteReg(REG_FSCAL0,VAL_FSCAL0);
WriteReg(REG_RCCTRL1,VAL_RCCTRL1);
WriteReg(REG_RCCTRL0,VAL_RCCTRL0);
WriteReg(REG_FSTEST,VAL_FSTEST);
WriteReg(REG_TEST2,VAL_TEST2);
WriteReg(REG_TEST1,VAL_TEST1);
WriteReg(REG_TEST0,VAL_TEST0);
WriteReg(REG_DAFUQ,VAL_DAFUQ);
}