Using DeadOn DS3234 for Dimming LEDS (Arduino UNO)

Hello

I'm very new to this, and would greatly appreciate your thoughts...

I am trying to get 4 LEDs to change in brightness with each change in minute (The work is for an art installation, and the brightnesses have been specifically chosen). I am using the DeadOn RTC Breakout.

I started with the sketch from the SparkFun DS3234 Arduino Library (DSC3234_RTC_Demo.ino), and added/subtracted to get to the following:

#include <SPI.h>
#include <SparkFunDS3234RTC.h>

#define DS13074_CS_PIN 10 // DeadOn RTC Chip-select pin

 const int panel1Pin = 3;
 const int panel2Pin = 5;
 const int panel3Pin = 6;
 const int panel4Pin = 9;

int digit1 = 0; //integer for first digit of hour
int digit2 = 0; //integer for second digit of hour
int digit3 = 0; //integer for first digit of minute
int digit4 = 0; //integer for second digit of minute

int segmentCount[] = {6, 2, 5, 5, 4, 5, 6, 3, 7, 6};  //number of segments in digits 0 - 9

int segmentDigit1 = 0;  //number of segments in digit 1
int segmentDigit2 = 0;  //number of segments in digit 2
int segmentDigit3 = 0;  //number of segments in digit 3
int segmentDigit4 = 0;  //number of segments in digit 4

/*
 * intensity values for number of segments lit are either mathematically accurate (255/7) or
 * based upon visual clarity
 */

int intensityCount[] = {0, 36, 73, 109, 146, 182, 219, 255};  //mathematically accurate
// int intensityCount[] = {0, 0, 5, 15, 35, 75, 140, 255}; //visual clarity

int panelIntensity1 = 0;
int panelIntensity2 = 0;
int panelIntensity3 = 0;
int panelIntensity4 = 0;

void setup() 
{
  // Use the serial monitor to view time/date output
  Serial.begin(9600);

  // Call rtc.begin([cs]) to initialize the library
  // The chip-select pin should be sent as the only parameter
  rtc.begin(DS13074_CS_PIN);

  rtc.setTime(0, 8, 7, 7, 22, 9, 18);
}

void loop() 
{
  static int8_t lastMinute = -1;
  // Call rtc.update() to update all rtc.seconds(), rtc.minutes(),
  // etc. return functions.
  rtc.update();

  if (rtc.minute() != lastMinute) // If the minute has changed
  {
    printTime(); // Print the new time
    printDigit(); // Print the individual digit values
    printIntensity(); // Print the lamp intensity for each digit

    lightLamp(); // Send PWM data to LEDs

    lastMinute = rtc.minute(); // Update lastMinute value
  } 
}

void printTime()
{
  Serial.print(String(rtc.hour()) + ":"); // Print hour
  if (rtc.minute() < 10)
    Serial.print('0'); // Print leading '0' for minute
  Serial.print(String(rtc.minute()) + ":"); // Print minute
  if (rtc.second() < 10)
    Serial.print('0'); // Print leading '0' for second
  Serial.println(String(rtc.second())); // Print second
}

void printDigit()
{
  if (rtc.hour() < 10)                    //digit 1
        digit1 = 0;
  else if (rtc.hour() >= 10)
        digit1 = (rtc.hour() / 10);
        digit2 = (rtc.hour() % 10);       //digit 2
  if (rtc.minute() < 10)                  //digit 3
        digit3 = 0;
  else if (rtc.minute() >= 10)
        digit3 = (rtc.minute() / 10);
        digit4 = (rtc.minute() % 10);     //digit 4
  Serial.print(digit1);
  Serial.print("|");
  Serial.print(digit2);
  Serial.print("|");
  Serial.print(digit3);
  Serial.print("|");
  Serial.print(digit4);
  Serial.println("|");
}

void printIntensity()
{
  // identify number of segments in each digit
  segmentDigit1 = segmentCount[digit1];
  segmentDigit2 = segmentCount[digit2];
  segmentDigit3 = segmentCount[digit3];
  segmentDigit4 = segmentCount[digit4];
  
  //identify intensity for number of segments
  panelIntensity1 = intensityCount[segmentDigit1];
  panelIntensity2 = intensityCount[segmentDigit2];
  panelIntensity3 = intensityCount[segmentDigit3];
  panelIntensity4 = intensityCount[segmentDigit4];

  Serial.print(panelIntensity1);
  Serial.print("|");
  Serial.print(panelIntensity2);
  Serial.print("|");
  Serial.print(panelIntensity3);
  Serial.print("|");
  Serial.print(panelIntensity4);
  Serial.println("|");
}

void lightLamp()
{
  analogWrite(panel1Pin, panelIntensity1);
  analogWrite(panel2Pin, panelIntensity2);
  analogWrite(panel3Pin, panelIntensity3);
  analogWrite(panel4Pin, panelIntensity4);
}

I have also attached an image of the circuit.

When it works, it works well! But it flips out from time to time, and will either stick in the occasional unexpected result, or start streaming unexpected results:

9:57:00
0|9|5|7|
219|219|182|109|
9:58:00
0|9|5|8|
219|219|182|255|
9:59:00
0|9|5|9|
219|219|182|219|
10:00:00
1|0|0|0|
73|219|219|219|
4:40:00 This is where it starts going wrong (for example)
0|4|4|0|
219|146|146|219|
10:00:01
1|0|0|0|
73|219|219|219|

Does anyone have any idea what I have done wrong?

Thanks in advance for any help you can give.

Best wishes

Rav

Note - the issue does not happen if I comment out:

lightLamp()

This might be off the wall, but try using a different, non-pwm pin for the RTC select. You're using pin 10. try changing that to pin 4, for example.

The only RTC I have uses i2c , not SPI, so I can't check for similarities

As an addendum to my previous post , also try using pins 4,6,9 and 10 for your LEDs.

My thinking here is that using PWM on pin 3 may have some effect on SPI timing (pin 11). Pin 3 and pin 11 share the same timer.

As I said in my previous post, it is off the wall but....

Thank you darrob,

I tried the changes suggested (except I used pins 5,6,9,10 for the LEDs), but unfortunately its still not performing as I'd hoped:

9:23:00 - correct
0|9|2|3|
219|219|182|182|
10:164:07 - unexpected
1|0|16|4|
73|219|-3634|146|
9:23:05 - unexpected
0|9|2|3|
219|219|182|182|
9:24:00 - correct
0|9|2|4|
219|219|182|146|
9:25:00 - correct
0|9|2|5|
219|219|182|182|
14:00:00 - unexpected
1|4|0|0|
73|146|219|219|
9:25:00 - correct but unexpected duplicate
0|9|2|5|
219|219|182|182|

I have also noticed that the unexpected results are exactly repeated if I rerun the program.

Thanks for taking the time to have a look darrob.

Cheers

Rav

Hi

I've not been able to reproduce your errors with my setup.

As I said, I only have an RTC that uses I2C comms.

However, I do have a couple of thoughts. All speculation.

  • You're calling rtc.update() every loop cycle. With the code this small, it's being called every millisecond (or close to it.) Add some code to call say every 50ms. -- if ((unsigned long)(millis() - lastmillis >= 15)) --
  • You're calling rtc.update() then immediately following it up with calls to read from the data. I've done exactly the same thing and have had no issues, but I wonder if the fact that you're using SPI might require a small delay before you access the data. Try inserting a delay(1) between rtc.update() and rtc.minute(). That will introduce a 1 millisecond delay between reading the RTC and accessing the data.
  • You may have a defective unit. Are you able to try another?
  • Last you could try using a unit similar to mine, (DS1307 RTC). I got mine as part of a cheap clone kit from HK

Sorry I can't help you more on this.
Let us know if you get it sorted out

Cheers...

Hi darrob

Thank you so much - I inserted a delay between rtc.update() and rtc.minute(), and it seems to have worked! I'll run it for the next 24 hours and check the results before I get too excited, but from the initial results your suggestion was the solution. I have ordered an i2c RTC just incase though!

I'm very grateful for your help darrob.

Best

Rav