5
\$\begingroup\$

I had the ATtiny working with the shift register, but when I added the IR receiver to the code the shift register did not work as desired.

I have a shift register connected to 8 LEDs and controlled by an ATtiny85. I also have a button and an IR receiver connected. The idea is to control the LEDs with my remote control using the minimal space required for an ATtiny.

It is definitely in the code, because it was working with the code for only the shift register and all that changed in the hardware was the addition of a button and IR sensor. The shift register only turns on all the lights and eventually turns them all off. what I want to happen is patterns to be displayed on the LEDs.

Here is my code:

Hardware connections:

74HC595 pin  LED pin   Arduino pin

    1            (QB)      LED 2 +
    2            (QC)      LED 3 +
    3            (QD)      LED 4 +
    4            (QE)      LED 5 +
    5            (QF)      LED 6 +
    6            (QG)      LED 7 +
    7            (QH)      LED 8 +
    8            (GND)     GND

    9            (QH*)
    10           (SRCLR*)  5 V
    11           (SRCLK)   Digital 3
    12           (RCLK)    Digital 4
    13           (OE*)     GND
    14           (SER)     Digital 2
    15           (QA)      LED 1 +
    16           (VCC)     5 V

*/

// Pin definitions:
// The 74HC595 uses a type of serial connection called SPI
// (Serial Peripheral Interface) that requires three pins:

int datapin = 2;
int clockpin = 3;
int latchpin = 4;
int switchpin = 1;

// We'll also declare a global variable for the data we're
// sending to the shift register:

/* Raw IR commander

   This sketch/program uses the Arduno and a PNA4602 to
   decode IR received.  It then attempts to match it to a previously
   recorded IR signal

   Code is public domain, check out www.ladyada.net and adafruit.com
   for more tutorials!
*/

// We need to use the 'raw' pin reading methods
// because timing is very important here and the digitalRead()
// procedure is slower!
//
//uint8_t IRpin = 2;
//
// Digital pin #2 is the same as Pin D2 see
// http://arduino.cc/en/Hacking/PinMapping168 for the 'raw' pin mapping
#define IRpin_PIN      PINB
#define IRpin          0

// The maximum pulse we'll listen for - 65 milliseconds is a long time
#define MAXPULSE 65000
#define NUMPULSES 50

// What our timing resolution should be, larger is better
// as its more 'precise' - but too large and you wont get
// accurate timing.
#define RESOLUTION 20

// What percent we will allow in variation to match the same code
#define FUZZINESS 20

// We will store up to 100 pulse pairs (this is -a lot-)
uint16_t pulses[NUMPULSES][4];  // Pair is high and low pulse
uint8_t currentpulse = 0;       // Index for pulses we're storing

#include "ircodes.h"

byte data = 0;
int m = 0;
int paterns = 6;

void setup()
{
    // Set the three SPI pins to be outputs:

    pinMode(datapin, OUTPUT);
    pinMode(clockpin, OUTPUT);
    pinMode(latchpin, OUTPUT);
    digitalWrite(switchpin, HIGH);
}


void loop()
{
    int numberpulses;

    numberpulses = listenForIR();

    if (IRcompare(numberpulses, center,sizeof(center)/4)) {

    }
    if (IRcompare(numberpulses, left,sizeof(left)/4)) {
        if (m>0) {
            m = (m-1);
        }
        else {
            m = paterns;
        }
    }
    if (IRcompare(numberpulses, right,sizeof(right)/4)) {
        m = (m+1)%paterns;
    }

    if (digitalRead(switchpin) == LOW)
    {
        m = (m+1)%paterns;
        delay(800);
    }

    switch (m) {
        case 0:
            oneAfterAnother();  // All on, all off
            break;
        case 1:
            oneOnAtATime();     // Scroll down the line
            break;
        case 2:
            pingPong();         // Like above, but back and forth
            break;
        case 3:
            randomLED();        // Blink random LEDs
            break;
        case 4:
            marquee();          // like an old movie theater
            break;
        case 5:
            binaryCount();      // Bit patterns from 0 to 255
            break;
        }
    }


void shiftWrite(int desiredPin, boolean desiredState)

// This function lets you make the shift register outputs
// HIGH or LOW in exactly the same way that you use digitalWrite().

// Like digitalWrite(), this function takes two parameters:

//    "desiredPin" is the shift register output pin
//    you want to affect (0-7)

//    "desiredState" is whether you want that output
//    to be HIGH or LOW

// Inside the Arduino, numbers are stored as arrays of "bits",
// each of which is a single 1 or 0 value. Because a "byte" type
// is also eight bits, we'll use a byte (which we named "data"
// at the top of this sketch) to send data to the shift register.
// If a bit in the byte is "1", the output will be HIGH. If the bit
// is "0", the output will be LOW.

// To turn the individual bits in "data" on and off, we'll use
// a new Arduino commands called bitWrite(), which can make
// individual bits in a number 1 or 0.
{
    // First we'll alter the global variable "data", changing the
    // desired bit to 1 or 0:

    bitWrite(data,desiredPin,desiredState);

    // Now we'll actually send that data to the shift register.
    // The shiftOut() function does all the hard work of
    // manipulating the data and clock pins to move the data
    // into the shift register:

    shiftOut(datapin, clockpin, MSBFIRST, data);

    // Once the data is in the shift register, we still need to
    // make it appear at the outputs. We'll toggle the state of
    // the latchPin, which will signal the shift register to "latch"
    // the data to the outputs. (Latch activates on the high-to
    // -low transition).

    digitalWrite(latchpin, HIGH);
    digitalWrite(latchpin, LOW);
}


/*
oneAfterAnother()

This function will light one LED, delay for delayTime, then light
the next LED, and repeat until all the LEDs are on. It will then
turn them off in the reverse order.
*/

void oneAfterAnother()
{
    int index;
    int delayTime = 100; // Time (milliseconds) to pause between LEDs
                         // Make this smaller for faster switching

    // Turn all the LEDs on:

    // This for() loop will step index from 0 to 7
    // (putting "++" after a variable means add one to it)
    // and will then use digitalWrite() to turn that LED on.

    for(index = 0; index <= 7; index++)
    {
        shiftWrite(index, HIGH);
        delay(delayTime);
    }

    // Turn all the LEDs off:

    // This for() loop will step index from 7 to 0
    // (putting "--" after a variable means subtract one from it)
    // and will then use digitalWrite() to turn that LED off.

    for(index = 7; index >= 0; index--)
    {
        shiftWrite(index, LOW);
        delay(delayTime);
    }
}


/*
oneOnAtATime()

  This function will step through the LEDs, lighting one at at time.
*/

void oneOnAtATime()
{
    int index;
    int delayTime = 100; // Time (milliseconds) to pause between LEDs
                         // Make this smaller for faster switching

    // step through the LEDs, from 0 to 7

    for(index = 0; index <= 7; index++)
    {
        shiftWrite(index, HIGH);  // Turn LED on
        delay(delayTime);         // Pause to slow down the sequence
        shiftWrite(index, LOW);   // Turn LED off
    }
}


/*
pingPong()

  This function will step through the LEDs, lighting one at at time,
  in both directions.
*/

void pingPong()
{
    int index;
    int delayTime = 100; // Time (milliseconds) to pause between LEDs
                         // make this smaller for faster switching.

    // Step through the LEDs, from 0 to 7

    for(index = 0; index <= 7; index++)
    {
        shiftWrite(index, HIGH);  // Turn LED on
        delay(delayTime);         // Pause to slow down the sequence
        shiftWrite(index, LOW);   // Turn LED off
    }

    // Step through the LEDs, from 7 to 0

    for(index = 7; index >= 0; index--)
    {
        shiftWrite(index, HIGH);  // Turn LED on
        delay(delayTime);         // Pause to slow down the sequence
        shiftWrite(index, LOW);   // Turn LED off
    }
}


/*
randomLED()

  This function will turn on random LEDs. Can you modify it so it
  also lights them for random times?
*/

void randomLED()
{
    int index;
    int delayTime = 100; // Time (milliseconds) to pause between LEDs
                         // make this smaller for faster switching.

    // The random() function will return a semi-random number each
    // time it is called. See http://arduino.cc/en/Reference/Random
    // for tips on how to make random() more random.

    index = random(8);   // Pick a random number between 0 and 7

    shiftWrite(index, HIGH);  // Turn LED on
    delay(delayTime);         // Pause to slow down the sequence
    shiftWrite(index, LOW);   // Turn LED off
}


/*
marquee()

  This function will mimic "chase lights" like those around signs.
*/

void marquee()
{
    int index;
    int delayTime = 200; // Time (milliseconds) to pause between LEDs.
                         // Make this smaller for faster switching.

    // Step through the first four LEDs
    // (We'll light up one in the lower 4 and one in the upper 4)

    for(index = 0; index <= 3; index++)
    {
        shiftWrite(index, HIGH);    // Turn a LED on.
        shiftWrite(index+4, HIGH);  // Skip four, and turn that LED on.
        delay(delayTime);           // Pause to slow down the sequence.
        shiftWrite(index, LOW);     // Turn both LEDs off.
        shiftWrite(index+4, LOW);
    }
}


/*
binaryCount()

  Numbers are stored internally in the Arduino as arrays of "bits",
  each of which is a 1 or 0. Just like the base-10 numbers we use
  every day, The position of the bit affects the magnitude of its
  contribution to the total number:

  Bit position   Contribution
  0              1
  1              2
  2              4
  3              8
  4              16
  5              32
  6              64
  7              128

  To build any number from 0 to 255 from the above 8 bits, just
  select the contributions you need to make. The bits will then be
  1 if you use that contribution, and 0 if you don't.

  This function will increment the "data" variable from 0 to 255
  and repeat. When we send this value to the shift register and LEDs,
  you can see the on-off pattern of the eight bits that make up the
  byte. See http://www.arduino.cc/playground/Code/BitMath for more
  information on binary numbers.
*/

void binaryCount()
{
    int delayTime = 1000; // Time (milliseconds) to pause between LEDs
                          // Make this smaller for faster switching.

    // Send the data byte to the shift register:

    shiftOut(datapin, clockpin, MSBFIRST, data);

    // Toggle the latch pin to make the data appear at the outputs:

    digitalWrite(latchpin, HIGH);
    digitalWrite(latchpin, LOW);

    // Add one to data, and repeat!
    // (Because a byte type can only store numbers from 0 to 255,
    // if we add more than that, it will "roll around" back to 0
    // and start over).

    data++;

    // Delay so you can see what's going on:

    delay(delayTime);
}

//IR functions

boolean IRcompare(int numpulses, int Signal[], int refsize) {
    int count = min(numpulses,refsize);
    for (int i=0; i< count-1; i++) {
        int oncode = pulses[i][5] * RESOLUTION / 10;
        int offcode = pulses[i+1][0] * RESOLUTION / 10;

        if ( abs(oncode - Signal[i*2 + 0]) <= (Signal[i*2 + 0] * FUZZINESS / 100)) {
        }
        else {
            return false;
        }

        if ( abs(offcode - Signal[i*2 + 1]) <= (Signal[i*2 + 1] * FUZZINESS / 100)) {
        }
        else {
            return false;
        }
    }
    return true;
}

int listenForIR(void) {
    currentpulse = 0;

    while (1) {
        uint16_t highpulse, lowpulse;  // Temporary storage timing
        highpulse = lowpulse = 0;      // Start out with no pulse length
        //  while (digitalRead(IRpin)) { // This is too slow!
        while (IRpin_PIN & (1 << IRpin)) {
           // Pin is still HIGH

           // Count off another few microseconds
           highpulse++;
           delayMicroseconds(RESOLUTION);

           // If the pulse is too long, we 'timed out' - either nothing
           // was received or the code is finished, so print what
           // we've grabbed so far, and then reset.

           // KGO: Added check for end of receive buffer
           if (((highpulse >= MAXPULSE) && (currentpulse != 0))|| currentpulse == NUMPULSES) {
               return currentpulse;
           }
        }
        // We didn't time out so lets stash the reading
        pulses[currentpulse][0] = highpulse;

        // same as above
        while (! (IRpin_PIN & _BV(IRpin))) {
            // pin is still LOW
            lowpulse++;
            delayMicroseconds(RESOLUTION);
            // KGO: Added check for end of receive buffer
            if (((lowpulse >= MAXPULSE)  && (currentpulse != 0))|| currentpulse == NUMPULSES) {
                return currentpulse;
            }
        }
        pulses[currentpulse][6] = lowpulse;

        // We read one high-low pulse successfully, continue!
        currentpulse++;
    }
}
\$\endgroup\$
  • \$\begingroup\$ I check everything and its definitely the code! \$\endgroup\$ – skyfly200 Apr 8 '13 at 3:52
  • 1
    \$\begingroup\$ I just noticed that you call 'IRcompare' (in 'loop') with the second argument being "center", "left" and "right"...what are those? Where are they defined? \$\endgroup\$ – Philipp Horn Apr 8 '13 at 12:46
  • \$\begingroup\$ It is definitely in the code, because it was working with the code for only the shift register and all that changed in the hardware was the addition of a button and ir sensor. The shift register only turns on all the lights and eventually turns them all off. what I want to happen is patterns to be displayed on the leds. the center, left and right are arrays of ir code data to compare a recieved ir code to and they are initialized in a file I didn't post called ircodes.h. \$\endgroup\$ – skyfly200 Apr 8 '13 at 22:41
  • 1
    \$\begingroup\$ What clock source are you using for your tiny85? delayMicroseconds in most currently published arduino/attiny cores is off by a factor of 8 for MCUs clocked at 1MHz, which happens to be the factory default. \$\endgroup\$ – microtherion Apr 9 '13 at 3:42
  • \$\begingroup\$ Does it work when you remove the line with numberpulses = listenForIR();? - From a quick glance it looks like listenForIr() may loop indefinitely if no pulses are detected and will thus block any other processing. - Or, put in another way: Are you sure the listenForIr() will return? \$\endgroup\$ – JimmyB Apr 9 '13 at 10:30
1
\$\begingroup\$
  1. It looks like there is an issue with the AVR pin setup. To read input from the switch your pin mode should be INPUT_PULLUPand switch should be connected between the pin and the ground.

    pinMode(switchpin, INPUT_PULLUP);

  2. I don't see centre/left/right declared in the loop() function's scope. Is that intentional? Please check.

\$\endgroup\$
  • \$\begingroup\$ a few suggestions: 1) use comments on your code; 2) try to minimize the number of returns you use - listenforir() is a bad example; 3) make sure that your execution returns from listenforir() -> you can test that by assigning a known value to m before the switch / case statement. I suspect that your execution gets stuck in listenforir(). \$\endgroup\$ – dannyf Jan 21 '17 at 15:20

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.