Statistics
| Revision:

root / RF12 / examples / rgbRemote / rgbRemote.pde

History | View | Annotate | Download (4.3 KB)

1
//>>> The latest version of this code can be found at https://github.com/jcw/ !!
2
3
// Control some LED strips, using settings received by wireless
4
// 2010-10-01 <jcw@equi4.com> http://opensource.org/licenses/mit-license.php
5
// $Id: rgbRemote.pde 7763 2011-12-11 01:28:16Z jcw $
6
7
// see http://jeelabs.org/2010/06/15/remote-rgb-strip-control/
8
// and http://jeelabs.org/2010/10/03/software-pwm-at-1-khz/
9
//
10
// 2010-06-12: delayed init of RF12 driver, to make LED startup a bit quicker
11
// 2010-09-08: adapted for 2x rgb with 0..100% intensity control
12
// 2010-10-01: back to 255 intensity levels, but with new TCT0-based trick
13
//
14
// example settings:
15
//
16
//  off all     255,255,255,0,255,255,255,0,30s
17
//  min all     255,255,255,1,255,255,255,1,30s
18
//  max all     255,255,255,255,255,255,255,255,30s
19
//  max cold    255,115,38,255,255,115,38,255,30s
20
//  max medium  255,100,13,255,255,100,13,255,30s
21
//
22
//  calm warm   255,90,8,25,255,90,8,25,30s
23
//  max warm    255,90,8,255,255,90,8,255,30s
24
//
25
// TODO: save changes to EEPROM using interrupts, i.e. in the background
26
// TODO: staggered turn-on, to reduce the inrush current of time slot zero
27
28
#include <Ports.h>
29
#include <RF12.h>
30
#include <EEPROM.h>
31
32
#define DEBUG 0
33
34
#define BAND RF12_868MHZ // wireless frequency band
35
#define GROUP 5     // wireless net group
36
#define NODEID 30   // node id on wireless to which this sketch responds
37
#define NVALUES 8   // can be adjusted from 1..8 (must also adjust "masks")
38
39
static byte settings[NVALUES];  // 0 = red, 1 = green, 2 = blue, 3 = white
40
static byte slots[256];         // time slots, toggles whenever a bit is set
41
42
MilliTimer timer;
43
44
// which setting affects which I/O pin:
45
//  bits 0..3 = AIO1 .. AIO4
46
//  bits 4..7 = DIO1 .. DIO4
47
static const byte masks[NVALUES] = {
48
    0x20, 0x02, 0x80, 0x00, 0x08, 0x10, 0x01, 0x00
49
};
50
51
static void setupIO() {
52
    for (byte i = 0; i < NVALUES; ++i) {
53
        PORTC &= ~ (masks[i] & 0x0F);   // turn AIO pin off
54
        DDRC |= masks[i] & 0x0F;        // make pin an output
55
        PORTD &= ~ (masks[i] & 0xF0);   // turn DIO pin off
56
        DDRD |= masks[i] & 0xF0;        // make pin an output
57
    }    
58
}
59
60
static void prepareSlots() {
61
#if DEBUG
62
    Serial.print("RGB values:");
63
    for (byte i = 0; i < NVALUES; ++i) {
64
        Serial.print(' ');
65
        Serial.print(settings[i], DEC);
66
    }
67
    Serial.println();
68
#endif    
69
70
    // use 4th value as intensity control over RGB values
71
    settings[0] = (settings[0] * settings[3] + 127) / 255; 
72
    settings[1] = (settings[1] * settings[3] + 127) / 255; 
73
    settings[2] = (settings[2] * settings[3] + 127) / 255; 
74
    // also for the second RGB group
75
    settings[4] = (settings[4] * settings[7] + 127) / 255; 
76
    settings[5] = (settings[5] * settings[7] + 127) / 255; 
77
    settings[6] = (settings[6] * settings[7] + 127) / 255; 
78
79
    // fill the slots arrray with on-bits, as implied by the intensity values
80
    memset(slots, 0, sizeof slots);
81
    for (byte i = 0; i < NVALUES; ++i) {
82
        // get the requested PWM level
83
        word intensity = settings[i];
84
        // don't use intensities 1 and 254, as they would toggle within 4 us
85
        // convert 0..255 values to 0 = off, 2..254 = dimmed, 256 = on
86
        if (intensity > 0) ++intensity;     // change 1..255 to 2..256
87
        if (intensity == 255) ++intensity;  // change (original) 254 to 256
88
        // fill in the 1's
89
        byte mask = masks[i]; // map setting to corresponding I/O pin
90
        for (word i = 0; i < intensity; ++i)
91
            slots[i] |= mask;
92
    }
93
}
94
95
static void loadSettings() {
96
    for (byte i = 0; i < NVALUES; ++i)
97
        settings[i] = EEPROM.read(i);
98
    prepareSlots();
99
}
100
101
static void saveSettings() {
102
    for (byte i = 0; i < NVALUES; ++i)
103
        EEPROM.write(i, settings[i]);
104
    prepareSlots();
105
}
106
107
static void showSettings() {
108
}
109
110
void setup () {
111
#if DEBUG
112
    Serial.begin(57600);
113
    Serial.println("\n[rgbRemote]");
114
#endif
115
    setupIO();
116
    loadSettings();
117
    rf12_initialize(NODEID, BAND, GROUP);
118
}
119
120
void loop() {
121
    if (timer.poll(100) && rf12_recvDone()
122
                        && rf12_hdr == (RF12_HDR_DST | NODEID)
123
                        && rf12_crc == 0 && rf12_len == NVALUES) {
124
        // turn LEDs off before making changes (saving takes time!)
125
        PORTC &= 0xF0;
126
        PORTD &= 0x0F;
127
        memcpy(settings, (void*) rf12_data, rf12_len);
128
        saveSettings();
129
    }
130
    byte bits = slots[TCNT0];
131
    PORTC = (PORTC & 0xF0) | (bits & 0x0F);
132
    PORTD = (PORTD & 0x0F) | (bits & 0xF0);
133
}