/*
Based on shiftRegister_softPWM_02
This program will automatically fade the LED on Q7
*/
const byte numChars = 32;
char receivedChars[numChars];
boolean newData = false;
#define NUMELEMENTS(x) (sizeof(x) / sizeof(x[0]))
// 74HC595 control
const uint8_t dataPin = 2;
const uint8_t clockPin = 3;
const uint8_t latchPin = 4;
// timing in microseconds
const uint32_t timerInterval = 2000;
// the starting intensities of the LEDs
//uint16_t pulseWidths[] = { 200 , 400, 600, 800, 1000, 1200, 2000 };
uint16_t pulseWidths[] = { 0, 0, 0, 0, 0, 0, 0 };
// index in pulseWidths for 74HC595 Q7
const uint8_t Q7 = 6;
uint8_t laPins[] = { 8, 9 };
void setup()
{
Serial.begin(115200);
Serial.println(F("74HC595 Software PWM 0.2"));
pinMode(dataPin, OUTPUT);
pinMode(clockPin, OUTPUT);
pinMode(latchPin, OUTPUT);
for (uint8_t cnt = 0; cnt < NUMELEMENTS(laPins); cnt++)
{
pinMode(laPins[cnt], OUTPUT);
}
}
void loop()
{
recvWithStartEndMarkers();
if (newData)
{
newData = false;
parseData();
}
fadeQ7();
softPWM();
}
void softPWM()
{
static uint32_t previousMicros;
uint32_t currentMicros = micros();
uint8_t data = 0;
if (currentMicros - previousMicros >= timerInterval)
{
previousMicros = currentMicros;
for (unsigned int i = 0; i < NUMELEMENTS(pulseWidths); i++)
{
if (pulseWidths[i] > 0)
{
data |= 1 << i;
}
}
}
else
{
for (unsigned int i = 0; i < NUMELEMENTS(pulseWidths); i++)
{
if (currentMicros - previousMicros >= pulseWidths[i])
{
data &= ~(1 << i);
}
}
}
digitalWrite(latchPin, LOW);
shiftOut(dataPin, clockPin, MSBFIRST, data << 1);
digitalWrite(latchPin, HIGH);
}
void fadeQ7()
{
uint32_t time = millis();
static uint32_t lastTime;
if(millis() - lastTime >= 50)
{
lastTime = millis();
pulseWidths[Q7] += 50;
if(pulseWidths[Q7] >= 2000)
{
pulseWidths[Q7] = 0;
}
}
}
void recvWithStartEndMarkers()
{
static boolean recvInProgress = false;
static byte ndx = 0;
char startMarker = '<';
char endMarker = '>';
char rc;
while (Serial.available() > 0 && newData == false)
{
rc = Serial.read();
if (recvInProgress == true)
{
if (rc != endMarker)
{
receivedChars[ndx] = rc;
ndx++;
if (ndx >= numChars)
{
ndx = numChars - 1;
}
}
else
{
receivedChars[ndx] = '\0'; // terminate the string
recvInProgress = false;
ndx = 0;
newData = true;
}
}
else if (rc == startMarker)
{
recvInProgress = true;
}
}
}
void parseData()
{ // split the data into its parts
char* strtokIndx; // this is used by strtok() as an index
strtokIndx = strtok(receivedChars, ","); // get the first part - the string
uint8_t ledNum = atoi(strtokIndx); // convert this part to an integer
strtokIndx = strtok(NULL, ","); // this continues where the previous call left off
int pwmVal = atoi(strtokIndx); // convert this part to an integer
if(ledNum == 0)
{
for(uint8_t cnt = 0; cnt < NUMELEMENTS(pulseWidths); cnt++)
{
pulseWidths[cnt] = pwmVal;
}
}
else
{
pulseWidths[ledNum - 1] = pwmVal;
}
}