Browse Source

First checking

Thomas Chef 8 years ago
commit
4ac3a6bdea
7 changed files with 765 additions and 0 deletions
  1. 96 0
      led_blink.ino
  2. 82 0
      luxsensor.ino
  3. 147 0
      nexa.ino
  4. 18 0
      queue.h
  5. 80 0
      queue.ino
  6. 227 0
      repeater.ino
  7. 115 0
      transmit.ino

+ 96 - 0
led_blink.ino

@@ -0,0 +1,96 @@
+// Declarations
+void ledBlinkFunction();
+
+// LED connected to digital pin 17
+const int LED_PIN = 17;
+
+unsigned int blinkLed;
+
+// Interface function to blink the yellow LED
+void blinkTheLED() {
+  blinkLed++;
+}
+
+void setup_timer_interrupt()
+{
+
+  // initialize digital led-pin as an output.
+  pinMode(LED_PIN, OUTPUT);
+
+  blinkLed = 0;
+
+  //set timer1 interrupt at 10Hz
+  TCCR1A = 0;// set entire TCCR1A register to 0
+  TCCR1B = 0;// same for TCCR1B
+  TCNT1  = 0;//initialize counter value to 0
+  // set compare match register for 1hz increments
+  
+  //  OCR1A = 40. This results is 16MHz / 8 / 40 = 20 uS between interrupts
+  OCR1A = 40;
+
+  // turn on CTC mode
+  TCCR1B |= (1 << WGM12);
+
+  // Set CS12:CS10 to 010 = /8 prescaler
+  TCCR1B |= (1 << CS11);  
+ 
+  // enable timer compare interrupt
+  TIMSK1 |= (1 << OCIE1A);
+}
+
+enum {
+  MODE_INACTIVE,
+  MODE_ON,
+  MODE_OFF,
+  MODE_SWITCH,   // Just have been off
+};
+
+// 10uS timer interrupt function
+ISR(TIMER1_COMPA_vect,ISR_NOBLOCK) {
+  
+  static unsigned int ledCnt=10000;
+  
+  rxInterrupt();
+  
+  if( (--ledCnt) == 0 ) {
+    ledCnt = 10000;
+    ledBlinkFunction();
+  }
+}  
+
+// 10Hz (100mS) timer interrupt function
+void ledBlinkFunction() {
+
+  static unsigned long timer = 0;
+  static int mode = MODE_INACTIVE;
+
+  switch( mode ) {
+
+  case   MODE_INACTIVE:
+    if( blinkLed > 0 ) {
+      blinkLed--;
+      mode = MODE_ON;
+      timer = 1;
+      digitalWrite(LED_PIN, LOW);   // turn the LED on (HIGH is the voltage level)
+    }
+    break;
+
+  case MODE_ON:
+    timer--;
+    if( timer == 0 ) {
+      mode = MODE_OFF;
+      digitalWrite(LED_PIN, HIGH);    // turn the LED off by making the voltage LOW
+      timer = 1;
+    }
+    break;
+
+  case MODE_OFF:
+    timer--;
+    if( timer == 0 ) {
+      mode = MODE_INACTIVE;
+      digitalWrite(LED_PIN, HIGH);    // turn the LED off by making the voltage LOW
+      break;
+
+    }
+  }
+}

+ 82 - 0
luxsensor.ino

@@ -0,0 +1,82 @@
+
+/* TSL25911 Digital Light Sensor */
+/* Dynamic Range: 600M:1 */
+/* Maximum Lux: 88K */
+
+#include <Wire.h>
+#include <Adafruit_Sensor.h>
+#include "Adafruit_TSL2591.h"
+
+Adafruit_TSL2591 tsl = Adafruit_TSL2591(2591); // pass in a number for the sensor identifier (for your use later)
+
+
+/**************************************************************************/
+/*
+    Configures the gain and integration time for the TSL2561
+*/
+/**************************************************************************/
+void configureSensor(void)
+{
+  // You can change the gain on the fly, to adapt to brighter/dimmer light situations
+  tsl.setGain(TSL2591_GAIN_LOW);    // 1x gain (bright light)
+  //tsl.setGain(TSL2591_GAIN_MED);      // 25x gain
+  //tsl.setGain(TSL2591_GAIN_HIGH);   // 428x gain
+  
+  // Changing the integration time gives you a longer time over which to sense light
+  // longer timelines are slower, but are good in very low light situtations!
+  tsl.setTiming(TSL2591_INTEGRATIONTIME_100MS);  // shortest integration time (bright light)
+  //tsl.setTiming(TSL2591_INTEGRATIONTIME_200MS);
+  //tsl.setTiming(TSL2591_INTEGRATIONTIME_300MS);
+  //tsl.setTiming(TSL2591_INTEGRATIONTIME_400MS);
+  //tsl.setTiming(TSL2591_INTEGRATIONTIME_500MS);
+  //tsl.setTiming(TSL2591_INTEGRATIONTIME_600MS);  // longest integration time (dim light)
+}
+
+/**************************************************************************/
+/*
+    Program entry point for the Arduino sketch
+*/
+/**************************************************************************/
+void initLuxSensor(void) 
+{   
+  if (tsl.begin()) 
+  {
+  } 
+  else 
+  {
+    Serial.println("No sensor found ... check your wiring?");
+    while (1);
+  }
+  /* Configure the sensor */
+  configureSensor();
+}
+
+/**************************************************************************/
+/*
+    Show how to read IR and Full Spectrum at once and convert to lux
+*/
+/**************************************************************************/
+uint32_t readLuxSensor(void)
+{
+  // More advanced data read example. Read 32 bits with top 16 bits IR, bottom 16 bits full spectrum
+  // That way you can do whatever math and comparisons you want!
+  uint32_t lum = tsl.getFullLuminosity();
+  uint16_t ir, full;
+  ir = lum >> 16;
+  full = lum & 0xFFFF;
+  //Serial.print("[ "); Serial.print(millis()); Serial.print(" ms ] ");
+  //Serial.print("IR: "); Serial.print(ir);  Serial.print("  ");
+  //Serial.print("Full: "); Serial.print(full); Serial.print("  ");
+  //Serial.print("Visible: "); Serial.print(full - ir); Serial.print("  ");
+  
+  uint32_t lux = tsl.calculateLux(full, ir);
+  
+  if ( (lux > 4294966000.0) ||
+       (lux <-4294966000.0) )
+  {
+    return 0;
+  }
+  else {
+    return lux;
+  }
+}

+ 147 - 0
nexa.ino

@@ -0,0 +1,147 @@
+
+enum { UNKNOWN, T0, T1, T2, T3, OK, DONE };
+
+byte state = UNKNOWN;
+
+       unsigned long x_data;
+static unsigned int x_numBits;
+static boolean x_2ndbit;
+
+static unsigned int dbg_periodTime; // For debugging
+
+static void resetDecoder () {
+	x_data = 0;
+	x_numBits = 0;
+	x_2ndbit = false;
+	state = UNKNOWN;
+}
+
+static boolean isDone() { return state == DONE; }
+
+static void done () { state = DONE; }
+
+static void gotBit (char value) {
+
+	// X
+	x_numBits++;
+	x_data = (x_data << 1) + (value & 0x01);
+	if( x_2ndbit == false ) {
+		x_2ndbit = true;
+	}
+	else {
+		x_2ndbit = false;
+		unsigned int bits = (x_data & 0x03);
+		if( bits == 2 ) {
+			// Bit is 1
+			x_data = (x_data >> 1) | 0x00000001;
+		}
+		else {
+			// Bit is 0
+			x_data = (x_data >> 1) & 0xFFFFFFFE;
+		}
+	}
+
+	state = OK;
+}
+
+static int decode (unsigned int width) {
+
+	switch (state) {
+	case UNKNOWN: // Start of frame
+		//printf("%8u\n",width);
+		if ( 2400 <= width && width <= 3000 ) {
+			state = T0;
+			//dbg_periodTime = width;
+		}
+		break;
+
+	case T0: // First half of pulse : HIGH around 230us
+
+		if ( 150 <= width && width <= 300 ) {
+			state = T1;
+		}
+                else if ( x_numBits == 0 && 2400 <= width && width <= 3000 ) {
+			state = T0;
+		}
+		else return -1;	// error, reset
+		break;
+
+	case T1:
+                if ( 200 <= width && width <= 400) {
+			gotBit(0);
+		} else if ( 1000 <= width && width <= 1500 ) {
+			gotBit(1);
+		} else if ( /*width > 5000 &&*/ x_numBits == 64) {	// end of frame
+			state = DONE;
+			return 1;
+		} else  {
+			return -1;
+		}
+		state = T0;
+		break;
+	}
+	return 0;
+}
+
+#define TOO_SHORT 100
+
+bool nextPulseNexa (unsigned int width) {
+/*	unsigned int decodew = 0;
+  
+	static unsigned int totw = 0;
+	static int mode=0;
+
+
+	if( state != T0 ) {
+
+		switch( mode ) {
+		case 0:
+			totw = width;
+			mode = 1;
+			break;
+		case 1:
+			if( width < TOO_SHORT ) {
+				totw += width;
+				mode = 2;
+			}
+			else {
+				decodew = totw;
+				totw = width;
+			}
+			break;
+		case 2:
+			totw += width;
+			//if( width < TOO_SHORT ) {  // This change caused less reception
+			//	mode = 2;
+			//}
+			//else {
+				mode = 1;
+			//}
+			break;
+		}
+	}
+	else {
+		// T0-State, send right through
+		decodew = totw;
+		totw = width;
+		if( width < TOO_SHORT ) {
+			mode = 2;
+		}
+		else {
+			mode = 1;
+		}
+	} */
+//decodew = width;
+	if( width > 0 ) {
+		if (state != DONE)
+
+			switch (decode(width)) {
+			case -1:
+				resetDecoder();
+				break;
+			case 1:  done();  break;
+		}
+	}
+	return isDone();
+}
+

+ 18 - 0
queue.h

@@ -0,0 +1,18 @@
+#ifndef ____queue__
+#define ____queue__
+
+
+
+#define NEXA_QUEUE_SIZE 700	// Queue size from Nexa-remotes
+
+
+unsigned char rcvDeQueue( unsigned int *value );
+unsigned char rcvEnQueue( unsigned int value );
+unsigned char rcvRollbackQueue();
+unsigned int getQueueUsed();
+void  rcvInitQueue(  );
+
+
+
+#endif
+

+ 80 - 0
queue.ino

@@ -0,0 +1,80 @@
+#include "queue.h"
+
+static int read_d;				/*!< Read index points to the place in the queue that has already been read */
+static int write_d;				/*!< The write index points to the place where the next write in the queue will take place. */
+
+static unsigned int nexaQueueBuffer[NEXA_QUEUE_SIZE];
+
+
+void  rcvInitQueue(  ) {
+    
+	read_d = 0;
+	write_d = 1;
+}
+
+unsigned int getQueueUsed() {
+  
+  return (write_d-read_d);
+}
+
+unsigned char rcvEnQueue( unsigned int value ) {
+    
+	// Is the queue full ?
+	if( write_d == read_d )
+	{
+		return 0u;
+	}
+    
+	// Make the data copy
+	nexaQueueBuffer[write_d] = value;
+    
+	// Increment the write position
+	write_d++;
+	if( write_d == NEXA_QUEUE_SIZE ) write_d=0;
+    
+	return 1u;
+}
+
+unsigned char  rcvDeQueue( unsigned int *value ) {
+    
+	int writePos = write_d;
+    
+	// Pseudo writepos
+	if( writePos < read_d || writePos == read_d ) writePos += NEXA_QUEUE_SIZE;
+    
+	// The queue is empty ?
+	if( writePos == ( read_d + 1 ) )
+	{
+		return 0u;
+	}
+    
+	// Increment the read position
+	read_d++;
+	if( read_d == NEXA_QUEUE_SIZE ) read_d=0; 
+    
+	// Make the data copy
+	*value = nexaQueueBuffer[read_d];
+    
+	return 1u;
+}
+
+// This function rolls back the latest inserted entry
+unsigned char rcvRollbackQueue() {
+
+	// Is the queue empty ?
+	if( write_d == ( read_d + 1 ) )
+	{
+		return 0u; // No rollback
+	}
+	
+	if( write_d == 0 ) {
+		write_d = NEXA_QUEUE_SIZE - 1;
+	}
+	else {
+		write_d--;
+	}
+
+	return 1u;
+}
+
+

+ 227 - 0
repeater.ino

@@ -0,0 +1,227 @@
+#include "queue.h"
+
+boolean disableRx = true;
+
+const int rxPinA      = 7;  // RX, Connected to pin 7
+const int enablePin   = 4;  // Enable, Connected to RTX pin 6: 0=Power down, 1=Active
+const int txEnablePin = 5;  // rx/TX, Connected to RTX pin 5: 0=Rx, 1=Tx
+const int txPin       = 6;  // TX, Connected to RTX pin 4
+
+
+//********************************************************************
+//                              SETUP
+//********************************************************************
+void setup() {
+  
+  disableRx = true;
+
+  pinMode(rxPinA, INPUT);
+  pinMode(enablePin, OUTPUT);
+  pinMode(txEnablePin, OUTPUT);  
+  pinMode(txPin, OUTPUT);  
+  
+  digitalWrite(enablePin, LOW);
+  digitalWrite(txEnablePin, LOW);
+  digitalWrite(txPin, LOW);  
+  
+  // ------------------ INIT THE TRANCEIVER -------------------------
+  // From powerdown mode (pin 4-5-6 low), 
+  // 1. Drive high pin 6 (ENABLE)
+  // 2. After 20us drive high pin 5 (RX/TX)200us, hold on 40us 
+  // 3. Drive down 20us pin 6 (ENABLE).  
+  digitalWrite(enablePin, HIGH); delayMicroseconds( 20 ); 
+  digitalWrite(txEnablePin, HIGH); delayMicroseconds( 200 ); digitalWrite(txEnablePin, LOW);
+  delayMicroseconds( 40 ); 
+  digitalWrite(enablePin, LOW); delayMicroseconds( 20 ); digitalWrite(enablePin, HIGH);  
+  delayMicroseconds( 200 );
+  // ------------------ INIT THE TRANCEIVER -------------------------  
+  
+  Serial.begin(9600);  // USB Serial
+  
+  initLuxSensor();    // Init the lux sensor on i2c
+
+  rcvInitQueue();
+  
+  cli(); // Clear interrupt
+
+  setup_timer_interrupt();
+  
+  sei(); // Enable interrupt
+  
+  disableRx = false;
+}
+
+//********************************************************************
+//                       INTERRUPT FUNCTIONS
+//********************************************************************
+
+void rxInterrupt() {
+  
+    static unsigned char currValue = 0;
+    static unsigned short samples = 0;
+    static unsigned short newSamples = 0;
+    
+    //return; // FOR DEBUG, Disables nexa receive
+
+    // Sample the pin value
+    unsigned char value = digitalRead(rxPinA);
+
+    if( value == currValue ) {
+        samples++;
+        samples+=newSamples;
+        newSamples=0;
+    }
+    else {
+        newSamples++;
+    }
+
+    if( newSamples == 3 ) {
+        rcvEnQueue(samples * 20);
+        samples = newSamples;
+        newSamples = 0;
+        currValue = value;    
+    }
+}
+
+void stopInterrupts() {
+    EIMSK &= 0xFC;      // Clear bit 1:0 in Enable Interrupt register
+}
+
+//********************************************************************
+//                           LOOP
+//
+// Test-code: <NT1B5C1D83>
+//********************************************************************
+#define SER_RX_MODE_WAIT 0
+#define SER_RX_MODE_RCV 1
+#define SER_RX_MODE_END 2
+
+extern unsigned long x_data; // Receive data from Nexa
+extern unsigned long temp1_x_data; // Receive data from temp1
+
+void loopB() {
+  
+  uint32_t lux = readLuxSensor();
+  
+  Serial.println(lux);
+  
+  delay(1000);
+  
+}
+
+void loop() {
+  
+  static int rxMode = SER_RX_MODE_WAIT;
+  static int rxNum = 0;
+  //static unsigned char rxChars[20];
+  
+  static unsigned long last_rx_time = 0;
+  
+  static unsigned char txDataReady = 0;
+  
+  static unsigned long previous_nexa_x_data = 0;
+  static unsigned long nexa_old_time=0;
+  
+  static unsigned long previous_temp1_x_data = 0;
+  static unsigned long temp1_old_time=0;
+  
+  //static char hex[100];
+  
+  static boolean firstRun = true;
+
+  static unsigned int width;
+  
+  static unsigned long txCode = 0;
+  
+  static unsigned long previous_lux_time = 20000; // Start 1st measure after 20 sec
+  
+  static unsigned long previous_now = 0; // Get the current time
+  unsigned long now = millis(); // Get the current time
+  
+  // Check millis() for wrapping (after 49 days)
+  if( previous_now > now ) {
+    last_rx_time = 0; // Reset last rx time    
+    previous_lux_time = 0;
+  }
+  
+  // Display version information 10 sec after startup
+  if( firstRun == true && now > 10000 ) {
+    Serial.println("433MHz Repeater module. (Arduino nano) Ver: 170211 14:46");  // **** VERSION ****
+    firstRun = false;
+  }
+  
+  if( now > previous_lux_time  ) {
+      // Yes ! It's time to measure lux value
+      int32_t lux = readLuxSensor();
+      
+      if( lux > 0xFFFF ) lux=0xFFFF;
+      if( lux < 0 ) lux=0;
+      
+      //Serial.println(lux);
+      
+      // Set next measure to 3 minutes +/- 20 sec
+      previous_lux_time = now + 170000 + (random(20)*1000);
+      
+      txDataReady = 1;
+                   
+      txCode  = 0x6AD50000;
+      txCode |= (lux & 0x0000FFFF);
+      
+      blinkTheLED();
+  }
+  
+  if( rcvDeQueue(&width) ) {
+    
+      // ********** NEXA ***********
+      if( nextPulseNexa(width) ) {
+        
+          last_rx_time = now;            // Set last rx time to now
+        
+          if( x_data != previous_nexa_x_data || now > (nexa_old_time+1000) ) {
+
+	    unsigned long  remote_id = (x_data & 0xFFFFFFC0) >>6;
+	    int group     = (x_data & 0x00000020) >>5;
+	    int onOff     = (x_data & 0x00000010) >>4;
+	    int channel   = (x_data & 0x0000000C) >>2;
+	    int button    = (x_data & 0x00000003);
+
+        Serial.println("Nexa");
+
+            if( remote_id == 11067169UL && txDataReady == 0 ) {
+              
+              remote_id++;
+              txDataReady = 1;
+              
+
+		txCode  = ((remote_id << 6) & 0xFFFFFFC0 );
+		txCode |= ((group     << 5) & 0x00000020 );
+		txCode |= ((onOff     << 4) & 0x00000010 );
+		txCode |= ((channel   << 2) & 0x0000000C );
+		txCode |= ((button        ) & 0x00000003 );
+              
+
+              //Serial.println(remote_id);
+              //Serial.println(onOff);
+            }
+
+              previous_nexa_x_data = x_data;
+          }
+          
+          nexa_old_time = now;
+          resetDecoder();
+          blinkTheLED();
+      }
+  }
+  
+  if( txDataReady == 1 && (now > (last_rx_time+200)) ) { // Transmit if it has passed more than 100mS since last rx
+    txDataReady = 0;
+    sendNexaCode(txCode);
+  }
+  
+  previous_now = now;  // Store to check for wrapping of millis()
+}
+
+
+
+
+

+ 115 - 0
transmit.ino

@@ -0,0 +1,115 @@
+
+
+void switch2transmit() {
+
+  disableRx = true;
+  // ------------------ GO TO TRANSMIT STATE -------------------------
+  digitalWrite(txEnablePin, HIGH);
+  delayMicroseconds( 400 );
+  // ------------------ GO TO TRANSMIT STATE -------------------------
+}
+
+void switch2receive() {
+  // ------------------ GO TO RECEIVE STATE -------------------------
+  // From Transmission Mode to Receiver Mode follow the procedure:
+  // Drive down pin 5 (RX/TX), after 40us drive down pin 6 (ENABLE) 20us long.
+  //After 200 us the device is ready for reception.
+  digitalWrite(txEnablePin, LOW); 
+  delayMicroseconds( 40 ); 
+  digitalWrite(enablePin, LOW); 
+  delayMicroseconds( 20 ); 
+  digitalWrite(enablePin, HIGH);  
+  delayMicroseconds( 200 );
+  // ------------------ GO TO RECEIVE STATE -------------------------
+  disableRx = false;
+}
+
+void sendPulse(int high, int low) {
+
+  digitalWrite(txPin, HIGH); 
+  delayMicroseconds( high ); 
+  digitalWrite(txPin, LOW); 
+  delayMicroseconds( low );  
+}
+
+// Nexa : http://elektronikforumet.com/wiki/index.php/RF_Protokoll_-_Nexa_sj%C3%A4lvl%C3%A4rande
+// "1" = 295 µs hög och 170 µs låg
+// "0" = 295 µs hög och 920 µs låg
+// 
+// Etta skickas som 10 och Nolla som 01
+//
+// Dessa siffror från web-sidan stämmer inte med den Nexa-kontroll som jag har.
+// Jag har rättat dessa med siffror från verkligheten. Finns i define's nedan.
+
+// <NT01995080>
+// <NT01995090>
+
+// Timing for NEXA Remote controls
+#define HIGH_PULSE     240
+#define LOW_PULSE_0    300
+#define LOW_PULSE_1   1300
+#define SYNC_PULSE    2700
+#define STOP_PULSE   10000
+
+void send1() {
+
+  sendPulse( HIGH_PULSE, LOW_PULSE_1);    // 1
+  sendPulse( HIGH_PULSE, LOW_PULSE_0 );   // 0
+}
+
+void send0() {
+
+  sendPulse( HIGH_PULSE, LOW_PULSE_0 );   // 0
+  sendPulse( HIGH_PULSE, LOW_PULSE_1);    // 1  
+}
+
+void sendSync() {
+  sendPulse( HIGH_PULSE, SYNC_PULSE );  
+}
+
+void sendStop() {
+  sendPulse( HIGH_PULSE, STOP_PULSE );
+}
+
+void sendNexaCode(unsigned long int txCode) {
+
+  unsigned long int code=0;
+  unsigned long int orig_code=txCode;  
+  int i;
+  int loop;
+
+  if( 1 == 1 ) {
+
+    // Turn off interrupts from the timer
+    TIMSK1 = 0;
+    
+    switch2transmit();
+
+    for( loop=6; loop>0; loop--) {
+      
+      code = orig_code;
+      
+      sendSync();
+
+      for(i=0; i < 32; i++) {
+
+        if( code & 0x80000000 ) {
+          send1();
+        }
+        else {
+          send0();
+        }
+        code = (code << 1);
+      }
+      sendStop();      
+    }
+
+    switch2receive();
+    
+    // Enable interrupts again
+    TIMSK1 |= (1 << OCIE1A);
+  }
+}
+
+
+