My kid's nightlamp (328P-PU+74HC595+ULN2003+DS1307 chips)

Hello all –

I am re-making my kid’s nightlamp, changing and adding some things from a previous project made this spring. The early version is comprised of an Atmel 328P-PU controlling a 28BYJ48 Stepper through its eval board (ULN2003A Darlington chip). Affixed to axle of stepper is a spindle that supports a small lampshade. Under the lampshade are a few 3mm LEDs that blink and PWM. On the paper lampshade are printed clipart sun, moon, stars, rockets, &c. The effect is basically blinking and fading blues, greens and oranges, backlighting slowly moving pictures. It works for my kid (14 mos.), which really works for his Dad (at kid’s bedtime).

The tweaks that I am having difficulty implementing at present are LED (PWM) control through the shift register that is non-blocking to the rotation of the stepper. More specifically, what I envision are LEDs whose fading (off-peak-off) will slow (longer duration), while decreasing in light emission (intensity) over, say, a 30 to 40 minute period. I am pretty sure the DS1307 clock chip can provide some assistance, and provide a timer function to put lamp to sleep (a couple LEDs lit continuous) at end of night, and turn off in the morning.

In the code I pasted, when the LEDs blink twice in the loop function, the stepper is blocked for that 400ms. If I can get past this, what I want is to eventually add another shift register for increased white light color scheme that seamlesly shifts to blue/green scheme through 30 minute cycle. I might have to move from fixed color LEDs to RGBs, but this still requires addition of second shift register.

I just got into electronics earlier this year, so my lack of experience, and mild case of neurasthenia in these matters, begs that I reach out to you folks. I have completed much research to get to this point, but have not found appropriate resource to guide me to some non-blocking code for the shift registers while allowing uninterrupted rotation of stepper. The code I have at present is all drawn from resources found in the Playgound and in this Forum. Photos included (hope they attached) of original version, Fritzing, and breadboard. Thank you in advance for your kind assistances.

Mark

/*
    18 Aug 2014 - Revision of Night Lamp
    Saving file as Nightlamp_Rev2.ino
    Also see file Nightlam_Rev2.fzz for breadboard wiring
    
*/

#include <Wire.h>
#include "RTClib.h"

RTC_DS1307 RTC;


//******Stepper motor stuff************
int motorPin1 = 14;    // White/Blue   - ULN2003APG/28BYJ48 pin 1
int motorPin2 = 15;    // Brown/Pink   - ULN2003APG/28BYJ48 pin 2
int motorPin3 = 16;    // Orange/Yellow - ULN2003APG/28BYJ48 pin 3
int motorPin4 = 17;    // Yellow/Orange - ULN2003APG/28BYJ48 pin 4
                        // Red    - from ULN2003APG pin 9 to 28BYJ48 pin 5 (VCC)
int motorSpeed = 6000;  //variable to set stepper speed // 14000 is practical
// For motorSpeed, consider mapping value from a potentiometer to value 6000 to 14000.
// Will require vacating pins PC0-3 to elsewhere (port B?), opening analog pins.
int count = 0;          // count of steps made
int countsperrev = 1024; // number of steps per full revolution
int lookup[8] = {B01000, B01100, B00100, B00110, B00010, B00011, B00001, B01001};

//******Shift register stuff**
//Pin connected to ST_CP of 74HC595
int latchPin = 8;  //attiny85v = 2;    // uno is 8, grn wire
//Pin connected to SH_CP of 74HC595
int clockPin = 12;  //attiny85v = 1;   //uno is 12, yel wire
//Pin connected to DS of 74HC595
int dataPin = 11;  //attiny85v = 0;    //uno is 11, blu wire

//holders for infromation you're going to pass to shifting function
byte data;
byte dataArray[9];   //[10]
// Timing of shift register activity
long previousTime = 0;
long interval = 5;    //this is in seconds and uses DS1307 chip
// Second pot to set LED cycle time? Cycle that dims and slows.
// Second pot map value to mins 20 - 60 called from DS1307

//*******setup****************
void setup() {
  //set pins to output because they are addressed in the main loop
  pinMode(latchPin, OUTPUT);
  Serial.begin(57600);
  Wire.begin();
  RTC.begin();
  
  pinMode(motorPin1, OUTPUT);
  pinMode(motorPin2, OUTPUT);
  pinMode(motorPin3, OUTPUT);
  pinMode(motorPin4, OUTPUT);
 
  if (! RTC.isrunning()) {
    Serial.println("RTC is NOT running!");
    // following line sets the RTC to the date & time this sketch was compiled
    //RTC.adjust(DateTime(__DATE__, __TIME__));
  }


  //Arduino doesn't seem to have a way to write binary straight into the code 
  //so these values are in HEX.  Decimal would have been fine, too. 
  dataArray[0] = 0xFF; //11111111
  dataArray[1] = 0xFE; //11111110
  dataArray[2] = 0xFC; //11111100
  dataArray[3] = 0xF8; //11111000
  dataArray[4] = 0xF0; //11110000
  dataArray[5] = 0xE0; //11100000
  dataArray[6] = 0xC0; //11000000
  dataArray[7] = 0x80; //10000000
  dataArray[8] = 0x00; //00000000
//  dataArray[9] = 0xE0; //11100000

//function that blinks all the LEDs
//gets passed the number of blinks and the pause time
  blinkAll_2Bytes(4,200);
  delay(2000);
}

void loop() {
    DateTime now = RTC.now();
    
    clockwise();
    
    unsigned long currentTime = now.unixtime();
    
    if(currentTime - previousTime > interval) {  // interval is in seconds
    // save the last time you blinked the LEDs 
    previousTime = currentTime;
    
    blinkAll_2Bytes(2,100);      //******nb - This causes approx 400ms stopping of rotation of stepper
    }
    
}

void shiftOut(int myDataPin, int myClockPin, byte myDataOut) {
  // This shifts 8 bits out MSB first, 
  //on the rising edge of the clock,
  //clock idles low

  //internal function setup
  int i=0;
  int pinState;
  pinMode(myClockPin, OUTPUT);
  pinMode(myDataPin, OUTPUT);

  //clear everything out just in case to
  //prepare shift register for bit shifting
  digitalWrite(myDataPin, 0);
  digitalWrite(myClockPin, 0);

  //for each bit in the byte myDataOut�
  //NOTICE THAT WE ARE COUNTING DOWN in our for loop
  //This means that %00000001 or "1" will go through such
  //that it will be pin Q0 that lights. 
  for (i=7; i>=0; i--)  {
    digitalWrite(myClockPin, 0);

    //if the value passed to myDataOut and a bitmask result 
    // true then... so if we are at i=6 and our value is
    // %11010100 it would the code compares it to %01000000 
    // and proceeds to set pinState to 1.
    if ( myDataOut & (1<<i) ) {
      pinState= 1;
    }
    else {  
      pinState= 0;
    }

    //Sets the pin to HIGH or LOW depending on pinState
    digitalWrite(myDataPin, pinState);
    //register shifts bits on upstroke of clock pin  
    digitalWrite(myClockPin, 1);
    //zero the data pin after shift to prevent bleed through
    digitalWrite(myDataPin, 0);
  }

  //stop shifting
  digitalWrite(myClockPin, 0);
}

void blinkAll_2Bytes(int n, int d) {
  digitalWrite(latchPin, 0);
  shiftOut(dataPin, clockPin, 0);
  shiftOut(dataPin, clockPin, 0);
  digitalWrite(latchPin, 1);
  delay(1);                //reduced from 30 or 50 ms
  for (int x = 0; x < n; x++) {
    digitalWrite(latchPin, 0);
    shiftOut(dataPin, clockPin, 255);
    shiftOut(dataPin, clockPin, 255);
    digitalWrite(latchPin, 1);
    delay(d);
    digitalWrite(latchPin, 0);
    shiftOut(dataPin, clockPin, 0);
    shiftOut(dataPin, clockPin, 0);
    digitalWrite(latchPin, 1);
    delay(d);
  }
}

void clockwise()
{
  for(int i = 7; i >= 0; i--)
  {
    setOutput(i);
    delayMicroseconds(motorSpeed);
  }
}

void setOutput(int out)
{
  digitalWrite(motorPin1, bitRead(lookup[out], 0));
  digitalWrite(motorPin2, bitRead(lookup[out], 1));
  digitalWrite(motorPin3, bitRead(lookup[out], 2));
  digitalWrite(motorPin4, bitRead(lookup[out], 3));
}

I’m not entirely sure what the problem is that your are having, perhaps you can distill it into a few bullet points rather than several paragraphs

I suspect however that your use of delay() may be the problem, as this a a very common posting to this forum.

Take a look at the BinkWithoutDelay example that is part of the standard Arduino install, also take a look a Finite State Machine coding (there is a library for this but its not rocket science and you can achieve the same thing with a variable and switch statement in a lot of cases)

Hi Mr. Clark –

Yes, delays in the code. So, I am using the DS1307 for purposes of testing, following the Blinkw/oDelay scheme, and call up the blinkAll_2Bytes(int n, int d) as shown in the loop function (code snip below). For “int d” (the delay) should I use the millis() function to time this? That block of code kind of got avoided as I am just grasping how these 595 chips work. The code I got from the ShiftOut tutorial here.

I will be looking to expand beyond just blinking a bank of LEDs into PWM’ing about 8 RGB LEDs (3 x 595 chips). To me this is getting a bit complicated as I look forward to figuring addressing these LEDs for color schemes.

Thanks for responding.

void loop() {
    DateTime now = RTC.now();
    
    clockwise();
    
    unsigned long currentTime = now.unixtime();  //from DS1307
    
    if(currentTime - previousTime > interval) {  // interval is in seconds
    // save the last time you blinked the LEDs 
    previousTime = currentTime;
    
    blinkAll_2Bytes(2,100);      //******nb - This causes approx 400ms stopping of rotation of stepper
    }
    
}

//**** other stuff ****

void blinkAll_2Bytes(int n, int d) {
  digitalWrite(latchPin, 0);
  shiftOut(dataPin, clockPin, 0);
  shiftOut(dataPin, clockPin, 0);
  digitalWrite(latchPin, 1);
  delay(1);                //reduced from 30 or 50 ms
  for (int x = 0; x < n; x++) {
    digitalWrite(latchPin, 0);
    shiftOut(dataPin, clockPin, 255);
    shiftOut(dataPin, clockPin, 255);
    digitalWrite(latchPin, 1);
    delay(d);
    digitalWrite(latchPin, 0);
    shiftOut(dataPin, clockPin, 0);
    shiftOut(dataPin, clockPin, 0);
    digitalWrite(latchPin, 1);
    delay(d);
  }
}

Why don't you use Arduino shiftOut() function instead of creating another?
And get rid of the delays inside the for() which is inside blink function.

Mart256 --

As I look at those functions I am unable to grasp how to merge the two for my purposes. These are the sort of details that elude me given my level of knowledge in these matters. Do you have suggestions for a resource that can guide me in this process?

Thank you for responding!

Mark