OverviewFilesCommitsIssuesDocsReleasesPeers

cthuloid / Arduino / DMX_LED_Controller / DMX_LED_Controller.ino

110 lines · ino ref:
#include <Conceptinetics.h>
#include <PWM.h>

// this flag will invert PWM output, for active-low devices
#define INVERT_HIGH_AND_LOW

int DMX_Address = 2;  // The DMX address of the first channel (using 1-based indexing)

// These pins will be mapped onto DMX channels in order (1-based indexing)
const int PWM_Pins[] = {7, 8, 44, 45};
const int Num_PWM_Pins = sizeof(PWM_Pins)/sizeof(*PWM_Pins);

const long PWM_Frequency = 1000;    // timer frequency for generating PWM
const long HR_PWM_Off = 2600;       // High Resolution PWM value at which our LED turns off

// map a log function while converting from 8-bits to 16-bits
// dmx: input [0-255]
// output: [2600-65535]
long DMXtoPWM(long dmx) {
  const float bottom = HR_PWM_Off;
  static const float coeff = log(65535.0 / bottom) / log(exp(1)) / 255;
  return round(bottom * exp(dmx * coeff));
}


//
// CTC-DRA-13-1 ISOLATED DMX-RDM SHIELD JUMPER INSTRUCTIONS
//
// If you are using the above mentioned shield you should 
// place the RXEN jumper towards G (Ground), This will turn
// the shield into read mode without using up an IO pin
//
// The !EN Jumper should be either placed in the G (GROUND) 
// position to enable the shield circuitry 
//   OR
// if one of the pins is selected the selected pin should be
// set to OUTPUT mode and set to LOGIC LOW in order for the 
// shield to work
//

//
// Pin number to change read or write mode on the shield
// Uncomment the following line if you choose to control 
// read and write via a pin
//
// On the CTC-DRA-13-1 shield this will always be pin 2,
// if you are using other shields you should look it up 
// yourself
//
///// #define RXEN_PIN                2


// Create a DMX slave controller
const int Num_DMX_Channels = Num_PWM_Pins;
DMX_Slave dmx_slave ( Num_DMX_Channels );

// If you are using an IO pin to control the shields RXEN
// the use the following line instead
///// DMX_Slave dmx_slave ( DMX_SLAVE_CHANNELS , RXEN_PIN );

void setup() {             
  Serial.begin(38400);

  Serial.print("DMX starting address: ");
  Serial.println(DMX_Address);
  dmx_slave.enable();  
  dmx_slave.setStartAddress(DMX_Address);

  // For high-resolution PWM, initialize all timers except for 0, to save time keeping functions
  InitTimersSafe(); 

  // initialize the first two pins
  for(int i = 0; i < Num_PWM_Pins - 2; i++) {
    Serial.print("setting PWM pin ");
    Serial.print(PWM_Pins[i]);
    Serial.print(" frequeny: ");
    Serial.println(SetPinFrequency(PWM_Pins[i], PWM_Frequency));
  }

  // the high resolution PWM library doesn't work for pins 44-45
  Serial.println("Setting pins 44-45 by different method");
  pinMode(44, OUTPUT);  // select Pin as ch-B
  pinMode(45, OUTPUT);  // select Pin as ch-C
 
  TCCR5A = B00101001; // Phase and frequency correct PWM change at OCRA
  TCCR5B = B10001;  // System clock
  OCR5A = 0xffff;   // max pwm value
}

void loop() 
{
  for(int i = 0; i < Num_PWM_Pins; i++) {
    int brightness = dmx_slave.getChannelValue(1 + i);
    
    //if(brightness > 0) Serial.println(brightness);

    // apply a logarithmic function to give finer control at lower brightness
    long hr = DMXtoPWM(brightness);
    
    //invert high and low
#ifdef INVERT_HIGH_AND_LOW
    hr = 65535 - hr;
#endif

    if(i < 2) pwmWriteHR(PWM_Pins[i], hr);
    if(i == 2) OCR5C = hr;    // mega pin 44
    if(i == 3) OCR5B = hr;    // mega pin 45
  }
}