help trying to convert a "lighthouse" program from softpwm to i2c

My goal for this project is to make a small ring of leds emulate the way a lighthouse light rotates around. My grandfather made several hand carved lighthouses, and I thought it might be nice for them to have lights in them. Rather that trying to fit moving Fresnel lens and lamps in it, I wanted a cheaper route. I found a site online that i would like to copy.

http://www.instructables.com/id/LED-Lighthouse-Light-Preliminary-Work/

He uses a Arduino Micro, 12v led strips, Two IC high speed transistor arrays tho control the leds.

i would like to copy the way he fades the leds around. My lists of parts include

  • pro trinket 3.3v
  • SX1509 I/O Expander Breakout board
  • cool white round 5mm leds ~3.3v
  • 220 ohm resisters for the leds
  • 2200ma lithium battery to power the internal regulator on ther trinket

The SX1509 is a 16-channel GPIO expander with an I2C interface that can pwm all 16 channels.

Here is the code that I am trying to convert from software pwm to use on the sx1509 board.

/*
  Lighthouse
  Turn on LEDs sequentially for a lighthouse effect.
 
  This example code is in the public domain.
 */

// Include appropriate libraries (SoftPWM)
#include <SoftPWM.h>     // Initialize SoftPWM

// Define the maximum number of pins for LED's and pin mappings, as well as value arrays for beam characteristics 
const int NLEDs=16;
int LEDpin[] = {3,4,5,6,7,8,9,10,11,12,13,A0,A1,A2,A3,A4}; // Map each of the LEDs to an arduino output pin
int RPM[] = {4,5,6,1,2,3};     // Number of sweeps per minute
int NBeams[] = {1,2,4};        // Number of evenly spaced LED beams
int Beamwidth [] = {1,2,3};    // Number of LEDs on per beam
int MaxBrightness=100;         // Define maximum brightness as a percentage 
int Index;

// Define pins connected to buttons, switchable indices for button settings and last button state
const int NButtons=3;
int Btnpin[] = {0,1,2};         // Map buttons to arduino input pins 
int Btnfunc[] = {0,0,0};        // Btnfunc[0]=iRPM, Btnfunc[1]=iNBeams, Btnfunc[2]=iBeamwidth
int Btnstate[]={LOW, LOW, LOW};
int iRPM, iNBeams, iBeamwidth;  // LED speed (in RPM), number of beams, and width of beams
int Debounce = 10;
unsigned long Interval, PreviousMillis; // Timing variables

void setup() {
   SoftPWMBegin(); // Initialize the SoftPWM library
   
// Initialize digital LED pins as OUTPUT
  int i;
  for (i=0; i<NLEDs; i++) pinMode(LEDpin[i], OUTPUT);

// Initialize buttons as INPUT and use internal pullup resistors
  for (i=0; i<NButtons; i++) pinMode(Btnpin[i],INPUT_PULLUP);
  
  check_buttons();
  
  Interval=(unsigned long)60000/(RPM[Btnfunc[0]]*NLEDs);
  PreviousMillis=millis();
  wipe_leds();
  set_pwm_fade();
  Index=-1;
  Serial.begin(9600);
}

void loop() {
  
  lighthouse_mode();
}

void lighthouse_mode() {
  int i,j,k, skip;
  check_buttons();
  if ((unsigned long)(millis() - PreviousMillis) >= Interval) {
    PreviousMillis=millis();   
    if (iRPM!=Btnfunc[0]) {set_pwm_fade(); iRPM=Btnfunc[0];}
    if (iNBeams!=Btnfunc[1]) {wipe_leds(); iNBeams=Btnfunc[1];}
    if (iBeamwidth!=Btnfunc[2]) {wipe_leds(); iBeamwidth=Btnfunc[2];}
    Interval=(unsigned long)60000/(RPM[iRPM]*NLEDs);
    set_pwm_fade();
    skip=NLEDs/NBeams[iNBeams];
    Index=(Index+1)%skip;
    for (j=0; j<NLEDs; j+=skip) {
      SoftPWMSetPercent(LEDpin[(Index+j+NLEDs-1)%NLEDs], 0);
      for(k=0;k<Beamwidth[iBeamwidth]; k++) SoftPWMSetPercent(LEDpin[(Index+j+k)%NLEDs], MaxBrightness);
    }
  }
}

void check_buttons() {
  int i, state;
  for (i=0; i<NButtons; i++) {
    state = digitalRead(Btnpin[i]);
    if (state!=Btnstate[i]) {
      Btnstate[i]=state;
      if (state==LOW) Btnfunc[i]=(Btnfunc[i]+1)%(i?3:6);
      delay(Debounce);   // Debouce delay
    }
  }
}

void wipe_leds(){
  int i;
  int j= (int)Interval;
  for (i=0; i<NLEDs; i++){
    SoftPWMSetFadeTime(LEDpin[i], 0,0); 
    SoftPWMSetPercent(LEDpin[i], 0);
    SoftPWMSetFadeTime(LEDpin[i], j,j); 
  }
}

void set_pwm_fade(){
  int i;
  int j= (int)Interval;
  for (i=0; i<NLEDs; i++) SoftPWMSetFadeTime(LEDpin[i], j,j);  
}

I have made slight progress converting it but i am stuck on the last few lines of code. “SoftPWMSetFadeTime” I am not sure how to replace that to fit with the sx1509 board.

Here is that mess that I have made so far.

/*
  Lighthouse
  Turn on LEDs sequentially for a lighthouse effect.
 
  This example code is in the public domain.
 */

// Include appropriate libraries (SoftPWM)
//#include <SoftPWM.h>     // Initialize SoftPWM



#include <Wire.h> // Include the I2C library (required)
#include <SparkFunSX1509.h> // Include SX1509 library

// SX1509 I2C address (set by ADDR1 and ADDR0 (00 by default):
const byte SX1509_ADDRESS = 0x3E;  // SX1509 I2C address 
SX1509 io; // Create an SX1509 object to be used throughout

// Define the maximum number of pins for LED's and pin mappings, as well as value arrays for beam characteristics 
const int NLEDs=16;
//int LEDpin[] = {3,4,5,6,7,8,9,10,11,12,13,A0,A1,A2,A3,A4}; // Map each of the LEDs to an arduino output pin
const int SX1509_LED_PIN[] = {0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15};
int RPM[] = {4,5,6,1,2,3};     // Number of sweeps per minute
int NBeams[] = {1,2,4};        // Number of evenly spaced LED beams
int Beamwidth [] = {1,2,3};    // Number of LEDs on per beam
int MaxBrightness=100;         // Define maximum brightness as a percentage 
int Index;

// Define pins connected to buttons, switchable indices for button settings and last button state
const int NButtons=3;
int Btnpin[] = {0,1,2};         // Map buttons to arduino input pins 
int Btnfunc[] = {0,0,0};        // Btnfunc[0]=iRPM, Btnfunc[1]=iNBeams, Btnfunc[2]=iBeamwidth
int Btnstate[]={LOW, LOW, LOW};
int iRPM, iNBeams, iBeamwidth;  // LED speed (in RPM), number of beams, and width of beams
int Debounce = 10;
unsigned long Interval, PreviousMillis; // Timing variables

void setup() {
 //  SoftPWMBegin(); // Initialize the SoftPWM library
   
// Initialize digital LED pins as OUTPUT
  int i;
  for (i=0; i<NLEDs; i++)  io.pinMode(SX1509_LED_PIN[i], ANALOG_OUTPUT);

// Initialize buttons as INPUT and use internal pullup resistors
  for (i=0; i<NButtons; i++) pinMode(Btnpin[i],INPUT_PULLUP);
  
  check_buttons();
  
  Interval=(unsigned long)60000/(RPM[Btnfunc[0]]*NLEDs);
  PreviousMillis=millis();
  wipe_leds();
  set_pwm_fade();
  Index=-1;
  Serial.begin(9600);
}

void loop() {
  
  lighthouse_mode();
}

void lighthouse_mode() {
  int i,j,k, skip;
  check_buttons();
  if ((unsigned long)(millis() - PreviousMillis) >= Interval) {
    PreviousMillis=millis();   
    if (iRPM!=Btnfunc[0]) {set_pwm_fade(); iRPM=Btnfunc[0];}
    if (iNBeams!=Btnfunc[1]) {wipe_leds(); iNBeams=Btnfunc[1];}
    if (iBeamwidth!=Btnfunc[2]) {wipe_leds(); iBeamwidth=Btnfunc[2];}
    Interval=(unsigned long)60000/(RPM[iRPM]*NLEDs);
    set_pwm_fade();
    skip=NLEDs/NBeams[iNBeams];
    Index=(Index+1)%skip;
    for (j=0; j<NLEDs; j+=skip) {
      io.analogWrite(SX1509_LED_PIN[(Index+j+NLEDs-1)%NLEDs], 0);
      for(k=0;k<Beamwidth[iBeamwidth]; k++) io.analogWrite(SX1509_LED_PIN[(Index+j+k)%NLEDs], MaxBrightness);
    }
  }
}

void check_buttons() {
  int i, state;
  for (i=0; i<NButtons; i++) {
    state = digitalRead(Btnpin[i]);
    if (state!=Btnstate[i]) {
      Btnstate[i]=state;
      if (state==LOW) Btnfunc[i]=(Btnfunc[i]+1)%(i?3:6);
      delay(Debounce);   // Debouce delay
    }
  }
}

void wipe_leds(){
  int i;
  int j= (int)Interval;
  for (i=0; i<NLEDs; i++){
    SoftPWMSetFadeTime(SX1509_LED_PIN[i], 0,0); 
    SoftPWMSetPercent(SX1509_LED_PIN[i], 0);
    SoftPWMSetFadeTime(SX1509_LED_PIN[i], j,j); 
  }
}

void set_pwm_fade(){
  int i;
  int j= (int)Interval;
  for (i=0; i<NLEDs; i++) SoftPWMSetFadeTime(SX1509_LED_PIN[i], j,j);  
}

Do I need to start form scratch? I am not the best at programming. Any help that you can give would greatly appreciated.

I would use a length of WS2812 LED strip, can control the fade up & down of each LED. What's the diameter you are encircling? Adafruit has some WS2812 LED circles too, maybe one would fit your tower already. Then use the Neopixel.h or the FastLed.h library to control them.

I thought about that, i even have a 16 and 12 ring neopixels from adafruit, but i wanted this to be as cheap as possible. The diameter i have to work with is 1.75 inches. I like the 5mm leds i have because at 3.3v thru a 220 ohm resistor they are only pulling about 4 ma. They also have a 15 deg throw. It will have more of a lighthouse look.

Okay, I have abandoned the idea of trying to convert the program. Now i am wondering how to write the softpwm library over i2c? Tis was i can just remap the output pins to the expander board and use digital write.