ATTiny 85 + Schieberegister + IR-Sensor

Ich hatte das ATtiny, das mit dem Schieberegister arbeitete, aber als ich den IR-Empfänger zum Code hinzufügte, funktionierte das Schieberegister nicht wie gewünscht.

Ich habe ein Schieberegister, das mit 8 LEDs verbunden ist und von einem ATtiny85 gesteuert wird. Ich habe auch einen Taster und einen IR-Empfänger angeschlossen. Die Idee ist, die LEDs mit meiner Fernbedienung zu steuern und dabei den minimalen Platzbedarf eines ATtiny zu nutzen.

Es ist definitiv im Code, weil es nur mit dem Code für das Schieberegister gearbeitet hat und alles, was sich in der Hardware geändert hat, das Hinzufügen einer Taste und eines IR-Sensors war. Das Schieberegister schaltet nur alle Lichter ein und schließlich alle aus. Ich möchte, dass Muster auf den LEDs angezeigt werden.

Hier ist mein Code:

Hardware-Verbindungen:

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++;
    }
}
Ich überprüfe alles und es ist definitiv der Code!
Ich habe gerade bemerkt, dass Sie 'IRcompare' (in 'loop') aufrufen, wobei das zweite Argument "center", "left" und "right" ist ... was sind das? Wo sind sie definiert?
Es ist definitiv im Code, weil es nur mit dem Code für das Schieberegister gearbeitet hat und alles, was sich in der Hardware geändert hat, das Hinzufügen einer Taste und eines IR-Sensors war. Das Schieberegister schaltet nur alle Lichter ein und schließlich alle aus. Was ich passieren möchte, sind Muster, die auf den LEDs angezeigt werden sollen. Die Mitte, links und rechts sind Arrays von IR-Code-Daten, mit denen ein empfangener IR-Code verglichen werden kann, und sie werden in einer Datei mit dem Namen ircodes.h initialisiert, die ich nicht gepostet habe.
Welche Taktquelle verwendest du für deinen tiny85? delayMicroseconds in den meisten derzeit veröffentlichten Arduino/Attiny-Kernen ist um den Faktor 8 für MCUs, die mit 1 MHz getaktet sind, was zufällig die Werkseinstellung ist.
Funktioniert es, wenn du die Zeile mit entfernst numberpulses = listenForIR();? - Auf den ersten Blick sieht es so aus, als listenForIr()würde es sich endlos wiederholen, wenn keine Impulse erkannt werden, und somit jede andere Verarbeitung blockieren. - Oder anders ausgedrückt: Bist du dir sicher, dass der listenForIr()wiederkommen wird?

Antworten (1)

  1. Es sieht so aus, als ob es ein Problem mit der AVR-Pin-Konfiguration gibt. Um die Eingabe vom Schalter zu lesen, sollte Ihr Pin-Modus sein INPUT_PULLUPund der Schalter sollte zwischen dem Pin und der Masse verbunden sein.

    pinMode(switchpin, INPUT_PULLUP);

  2. Ich sehe nicht, dass Mitte/Links/Rechts im loop()Gültigkeitsbereich der Funktion deklariert sind. Ist das beabsichtigt? Überprüfen Sie bitte.

ein paar Vorschläge: 1) Verwenden Sie Kommentare zu Ihrem Code; 2) Versuchen Sie, die Anzahl der verwendeten Rückgaben zu minimieren - listenforir() ist ein schlechtes Beispiel; 3) Stellen Sie sicher, dass Ihre Ausführung von listenforir () zurückkehrt -> Sie können dies testen, indem Sie m vor der switch / case-Anweisung einen bekannten Wert zuweisen. Ich vermute, dass Ihre Ausführung in listenforir() hängen bleibt.