515 lines
12 KiB
C++
515 lines
12 KiB
C++
#include <SPI.h>
|
|
#include "nRF24L01.h"
|
|
#include "RF24.h"
|
|
#include "printf.h"
|
|
#include "Adafruit_NeoPixel.h"
|
|
|
|
#define RADIOSEND false
|
|
|
|
#define CE_PIN 12
|
|
#define CSN_PIN 2
|
|
|
|
#define DEBUG 1
|
|
#define TEST 1
|
|
|
|
#define RED 11
|
|
#define GREEN 10
|
|
#define BLUE 9
|
|
#define WHITE 6
|
|
|
|
#define SDO1 8
|
|
#define SDO2 4
|
|
#define SDO3 3
|
|
|
|
#define NUMPIXELS1 300 // fuego
|
|
#define NUMPIXELS2 150
|
|
#define NUMPIXELS3 150
|
|
|
|
int idpin[4] = { A3, A4, 13, 5}; // A partir de 1 SLAVES
|
|
int chpin[4] = { A5, A0, A1, A2 }; // no se va a usar en esta App
|
|
|
|
Adafruit_NeoPixel pixels1 = Adafruit_NeoPixel(NUMPIXELS1, SDO1, NEO_GRBW + NEO_KHZ800);
|
|
Adafruit_NeoPixel pixels2 = Adafruit_NeoPixel(NUMPIXELS2, SDO2, NEO_GRBW + NEO_KHZ800);
|
|
Adafruit_NeoPixel pixels3 = Adafruit_NeoPixel(NUMPIXELS3, SDO3, NEO_GRBW + NEO_KHZ800);
|
|
|
|
RF24 radio(CE_PIN, CSN_PIN); // Create a Radio
|
|
const uint64_t pipe = 0xE8E8F0F0E1LL; // Define the transmit pipe
|
|
uint8_t CMD[ 4 ]; // CMD + Ch + 2
|
|
int ch = 76; // Fuerzo a canal 76 (showroom)
|
|
|
|
unsigned long delayed=0;
|
|
short stroboFlag = 0;
|
|
uint8_t param1=20;
|
|
uint8_t param2=140;
|
|
uint8_t mode = 0; // Modo OFF/TEST por defecto
|
|
uint8_t i = 0;
|
|
|
|
// Modo 1: FUEGO
|
|
// Modo 2: PixelPoint
|
|
// Modo 3: PixelBar
|
|
// Modo 4: StroboPixel
|
|
|
|
byte id()
|
|
{
|
|
int id = 0;
|
|
for (byte i = 0; i < 4; i++ ) bitWrite(id, i, digitalRead(idpin[i]));
|
|
return id;
|
|
}
|
|
|
|
|
|
int channel()
|
|
{
|
|
int value = code();
|
|
switch (value) {
|
|
case 0:
|
|
value = 0x4C; // showroom
|
|
break;
|
|
case 1:
|
|
value = 0x64; // developers
|
|
break;
|
|
default:
|
|
value = 0x64; // developers
|
|
break;
|
|
}
|
|
return value;
|
|
}
|
|
|
|
int code()
|
|
{
|
|
int value = 0;
|
|
for (byte i = 0; i < 4; i++) bitWrite(value, i, digitalRead(chpin[i]));
|
|
return value;
|
|
}
|
|
|
|
|
|
|
|
//////////////////////////////////////////////////////////////////
|
|
/////////////////////// NEON FUNCIONS ///////////////////
|
|
//////////////////////////////////////////////////////////////////
|
|
|
|
|
|
void stroboNeon(int stroboTime)
|
|
{
|
|
|
|
if ( millis() > delayed )
|
|
{
|
|
if ( stroboFlag )
|
|
{
|
|
analogWrite(WHITE, 255);
|
|
stroboFlag = 0;
|
|
Serial.println("Strobo_ON");
|
|
delayed = millis() + stroboTime;
|
|
}
|
|
else if ( !stroboFlag )
|
|
{
|
|
analogWrite(WHITE, 0);
|
|
Serial.println("Strobo_OFF");
|
|
stroboFlag = 1;
|
|
delayed = millis() + stroboTime;
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
void colorNeon(int red, int green, int blue)
|
|
{
|
|
|
|
analogWrite(RED, red);
|
|
analogWrite(GREEN, green);
|
|
analogWrite(BLUE, blue);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//////////////////////////////////////////////////////////////////
|
|
//////////////// PIXEL BASIC FUNCIONS //////////////////
|
|
//////////////////////////////////////////////////////////////////
|
|
|
|
void splitStrip()
|
|
{
|
|
// CONVERSION DE UNA ANIMACION DE 5M A DOS TRAMOS
|
|
|
|
for( int i = 0; i < 150 ; i++) // numPixels/2
|
|
{
|
|
|
|
pixels2.setPixelColor( i, pixels1.getPixelColor(i) );
|
|
pixels3.setPixelColor( i, pixels1.getPixelColor(i+150) );
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
void showStrip()
|
|
{
|
|
|
|
//pixels1.show(); // tira entera de 5m
|
|
pixels2.show(); // parte 1 de 2.5m
|
|
pixels3.show(); // parte 2 de 2.5m
|
|
|
|
}
|
|
|
|
void setPixel(int Pixel, byte red, byte green, byte blue, byte white)
|
|
{
|
|
|
|
pixels1.setPixelColor(Pixel, pixels1.Color(red, green, blue, white));
|
|
|
|
}
|
|
|
|
void setAll(byte red, byte green, byte blue, byte white)
|
|
{
|
|
|
|
for(int i = 0; i < NUMPIXELS1; i++ ) {
|
|
setPixel(i, red, green, blue, white);
|
|
}
|
|
|
|
splitStrip();
|
|
showStrip();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//////////////////////////////////////////////////////////////////
|
|
/////////////////////// PIXEL BAR //////////////////////
|
|
//////////////////////////////////////////////////////////////////
|
|
|
|
|
|
void pixelBar(int SpeedDelay, byte red, byte green, byte blue, byte white)
|
|
{
|
|
|
|
setAll(0,0,0,0);
|
|
|
|
for (int i = 0; i < NUMPIXELS1; i++)
|
|
{
|
|
|
|
setPixel(i, red, green, blue, white);
|
|
splitStrip();
|
|
showStrip();
|
|
delay(SpeedDelay);
|
|
|
|
}
|
|
}
|
|
|
|
|
|
//////////////////////////////////////////////////////////////////
|
|
/////////////////////// PIXEL POINT /////////////////////
|
|
//////////////////////////////////////////////////////////////////
|
|
|
|
|
|
void pixelPoint(int pixelPos, int pixWidth)
|
|
{
|
|
|
|
//setAll(0,0,0,0);
|
|
|
|
if( pixelPos > NUMPIXELS1 )
|
|
pixelPos=NUMPIXELS1;
|
|
if( pixelPos< 0 )
|
|
pixelPos= 0;
|
|
// pixels.Color takes RGB values, from 0,0,0 up to 255,255,255
|
|
pixels1.setPixelColor(pixelPos, pixels1.Color(255, 0, 0, 0)); // Moderately bright green color.
|
|
pixels1.setPixelColor(pixelPos-pixWidth, pixels1.Color(0, 0, 0, 0)); // Moderately bright green color.
|
|
|
|
splitStrip();
|
|
showStrip();
|
|
//delay(15);
|
|
|
|
// }
|
|
// else
|
|
// {
|
|
// //for (int i = NUMPIXELS1; i > 0; i--) {
|
|
// i--;
|
|
// if( i < 0 )
|
|
// i=NUMPIXELS1;
|
|
|
|
// // pixels.Color takes RGB values, from 0,0,0 up to 255,255,255
|
|
// pixels1.setPixelColor(i, pixels1.Color(0, 255, 255, 0)); // Moderately bright green color.
|
|
// pixels1.setPixelColor(i+pixWidth, pixels1.Color(0, 0, 0, 0)); // Moderately bright green color.
|
|
|
|
// splitStrip();
|
|
// showStrip();
|
|
// delay(SpeedDelay);
|
|
// //}
|
|
// }
|
|
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////
|
|
/////////////////////// PIXEL STROBO ////////////////////
|
|
//////////////////////////////////////////////////////////////////
|
|
|
|
|
|
void stroboPixel(int stroboTimeOn, int stroboTimeOff)
|
|
{
|
|
if ( millis() > delayed )
|
|
{
|
|
if ( stroboFlag )
|
|
{
|
|
stroboFlag = 0;
|
|
for (int i = 0; i < NUMPIXELS1; i++)
|
|
{
|
|
pixels1.setPixelColor(i, pixels1.Color(0, 0, 0, 255)); // Moderately bright green color.
|
|
}
|
|
splitStrip();
|
|
showStrip();
|
|
//analogWrite(WHITE, 255);
|
|
delayed = millis() + stroboTimeOn;
|
|
}
|
|
else if ( !stroboFlag )
|
|
{
|
|
stroboFlag = 1;
|
|
for (int i = 0; i < NUMPIXELS1; i++)
|
|
{
|
|
pixels1.setPixelColor(i, pixels1.Color(0, 0, 0, 0)); // Moderately bright green color.
|
|
|
|
}
|
|
splitStrip();
|
|
showStrip();
|
|
//analogWrite(WHITE, 0);
|
|
delayed = millis() + stroboTimeOff;
|
|
}
|
|
}
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////
|
|
/////////////////////// PIXEL FIRE //////////////////////
|
|
//////////////////////////////////////////////////////////////////
|
|
|
|
|
|
|
|
void fire(int Cooling, int Sparking, int SpeedDelay)
|
|
{
|
|
|
|
static byte heat[NUMPIXELS1];
|
|
int cooldown;
|
|
|
|
// Step 1. Cool down every cell a little
|
|
for( int i = 0; i < NUMPIXELS1 ; i++) {
|
|
cooldown = random(0, ((Cooling * 10) / NUMPIXELS1) + 2);
|
|
|
|
if(cooldown>heat[i]) {
|
|
heat[i]=0;
|
|
} else {
|
|
heat[i]=heat[i]-cooldown;
|
|
}
|
|
}
|
|
|
|
// Step 2. Heat from each cell drifts 'up' and diffuses a little
|
|
for( int k= NUMPIXELS1 - 1; k >= 2; k--) {
|
|
heat[k] = (heat[k - 1] + heat[k - 2] + heat[k - 2]) / 3;
|
|
}
|
|
|
|
// Step 3. Randomly ignite new 'sparks' near the bottom
|
|
if( random(255) < Sparking ) {
|
|
int y = random(7);
|
|
heat[y] = heat[y] + random(160,255);
|
|
//heat[y] = random(160,255);
|
|
}
|
|
|
|
// Step 4. Convert heat to LED colors
|
|
for( int j = 0; j < NUMPIXELS1; j++) {
|
|
setPixelHeatColor(j, heat[j] );
|
|
}
|
|
|
|
|
|
splitStrip();
|
|
showStrip();
|
|
delay(SpeedDelay);
|
|
|
|
}
|
|
|
|
void setPixelHeatColor (int Pixel, byte temperature)
|
|
{
|
|
// Scale 'heat' down from 0-255 to 0-191
|
|
byte t192 = round((temperature/255.0)*191);
|
|
|
|
// calculate ramp up from
|
|
byte heatramp = t192 & 0x3F; // 0..63
|
|
heatramp <<= 2; // scale up to 0..252
|
|
|
|
// figure out which third of the spectrum we're in:
|
|
if( t192 > 0x80) { // hottest
|
|
setPixel(Pixel, 255, 255, heatramp,0);
|
|
} else if( t192 > 0x40 ) { // middle
|
|
setPixel(Pixel, 255, heatramp, 0,0);
|
|
} else { // coolest
|
|
setPixel(Pixel, heatramp, 0, 0,0);
|
|
}
|
|
}
|
|
|
|
|
|
|
|
//////////////////////////////////////////////////////////////////
|
|
///////////////////////// SETUP ////////////////////////////////
|
|
//////////////////////////////////////////////////////////////////
|
|
|
|
|
|
void setup() {
|
|
|
|
|
|
pinMode(RED, OUTPUT);
|
|
digitalWrite(RED, LOW);
|
|
pinMode(GREEN, OUTPUT);
|
|
digitalWrite(GREEN, LOW);
|
|
pinMode(BLUE, OUTPUT);
|
|
digitalWrite(BLUE, LOW);
|
|
pinMode(WHITE, OUTPUT);
|
|
digitalWrite(WHITE, LOW);
|
|
|
|
for (int i = 0; i < 4; i++)
|
|
{
|
|
pinMode(idpin[i], INPUT);
|
|
pinMode(chpin[i], INPUT);
|
|
}
|
|
|
|
analogWrite(WHITE, 255);
|
|
analogWrite(RED, 255);
|
|
analogWrite(GREEN, 255);
|
|
analogWrite(BLUE, 255);
|
|
|
|
pixels1.begin();
|
|
pixels2.begin();
|
|
pixels3.begin();
|
|
pixels1.show(); // Initialize all pixels to 'off'
|
|
pixels2.show(); // Initialize all pixels to 'off'
|
|
pixels3.show(); // Initialize all pixels to 'off'
|
|
|
|
Serial.begin(512000);
|
|
//while (!Serial) {
|
|
// ; // wait for serial port to connect. Needed for Leonardo only
|
|
//}
|
|
|
|
//delay(5000);
|
|
analogWrite(WHITE, 0);
|
|
analogWrite(RED, 0);
|
|
analogWrite(GREEN, 0);
|
|
analogWrite(BLUE, 0);
|
|
|
|
printf_begin();
|
|
radio.begin();
|
|
radio.setDataRate( RF24_250KBPS );
|
|
radio.setPALevel( RF24_PA_MAX );
|
|
radio.setAutoAck(0);
|
|
radio.setPayloadSize(4);
|
|
radio.setChannel(ch);
|
|
#if RADIOSEND
|
|
radio.openWritingPipe(pipe);
|
|
#else
|
|
radio.openReadingPipe(1, pipe);
|
|
radio.startListening();
|
|
#endif
|
|
radio.printDetails();
|
|
|
|
|
|
}
|
|
|
|
|
|
//////////////////////////////////////////////////////////////////
|
|
///////////////////////// LOOP ////////////////////////////////
|
|
//////////////////////////////////////////////////////////////////
|
|
|
|
|
|
void loop()
|
|
{
|
|
if( TEST)
|
|
{
|
|
colorNeon(255,0,0);
|
|
fire(20, 140 ,5); // 55, 120, 15 (cooling 400 bajito e ir bajando para subir el tamaño hasta 20 maximo)
|
|
//pixelPoint(5,1,4);
|
|
//pixelPoint(5,0,4);
|
|
//stroboPixel(10,20);
|
|
//pixelBar(15, 0, 0, 0, 255);
|
|
}
|
|
else
|
|
{
|
|
if ( radio.available() )
|
|
{
|
|
|
|
while (radio.available())
|
|
{
|
|
//done = radio.read( CMD, sizeof(CMD) );
|
|
radio.read( CMD, sizeof(CMD) );
|
|
|
|
if (DEBUG)
|
|
{
|
|
//Serial.println("id: ");
|
|
//Serial.print(id());
|
|
|
|
//Serial.println("Got command");
|
|
|
|
for (int i = 0 ; i < 4 ; i++)
|
|
{
|
|
Serial.print(CMD[i]);
|
|
Serial.print(",");
|
|
}
|
|
Serial.println();
|
|
}
|
|
|
|
if ( ( CMD[0] == 201 ) && ( CMD[1] == id() ) ) // CMD 1
|
|
{
|
|
if (DEBUG)
|
|
{
|
|
Serial.print("Fuego: ");
|
|
}
|
|
mode = 1; // modo 1 = fuego
|
|
param1 = CMD[2];
|
|
param2 = CMD[3];
|
|
}
|
|
else if ( ( CMD[0] == 202 ) && ( CMD[1] == id() ) ) // CMD 2
|
|
{
|
|
if (DEBUG)
|
|
{
|
|
Serial.print("PixelPoint: ");
|
|
}
|
|
mode = 2; // modo 2 = punto
|
|
param1 = CMD[2];
|
|
param2 = CMD[3];
|
|
}
|
|
else if ( ( CMD[0] == 203 ) && ( CMD[1] == id() ) ) // CMD 3
|
|
{
|
|
if (DEBUG)
|
|
{
|
|
Serial.print("Strobo: ");
|
|
}
|
|
mode = 3; // modo 2 = punto
|
|
param1 = CMD[2];
|
|
param2 = CMD[3];
|
|
}
|
|
else if ( ( CMD[0] == 204 ) && ( CMD[1] == id() ) ) // CMD 4
|
|
{
|
|
if (DEBUG)
|
|
{
|
|
Serial.print("Color: ");
|
|
}
|
|
mode = 4; // modo 2 = punto
|
|
param1 = CMD[2];
|
|
param2 = CMD[3];
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
switch (mode)
|
|
{
|
|
case 1:
|
|
fire(param1, param2, 5); // (20,140,5) -> altura, chispas, delay
|
|
break;
|
|
case 2:
|
|
pixelPoint(param1,param2); // (5,1,4) -> pos, width
|
|
break;
|
|
case 3:
|
|
stroboPixel(param1,param2); // (5,1,4) -> delay, dir, width
|
|
break;
|
|
case 4:
|
|
setAll(param1,param2,0,0); // (5,1,4) -> delay, dir, width
|
|
colorNeon(param1, param2, 0);
|
|
break;
|
|
}
|
|
|
|
|
|
|
|
}
|