Forum: Mikrocontroller und Digitale Elektronik LIGHT_WS2812B Problem Attiny841


von Stefan S. (sschultewolter)


Lesenswert?

Hallo,

ich habe eine Frage, ob mir jemand bei diesen Problem helfen kann. 
Vorab, ich hatte auch in einem anderen Forum die Frage gestellt, bin mir 
aber nicht sicher, ob ich dort von vielen eine Antwort erwarten kann 
(ausser die üblichen Verdächtigen 
;))http://forum.arduino.cc/index.php?topic=363590.0

Es geht um die Ansteuerung von WS2812B-Leds mit einem Attiny841 sowie 
der LIGHT_WS2812 Libary in avr-gcc.
https://github.com/cpldcpu/light_ws2812/tree/master/light_ws2812_AVR/Light_WS2812

Ich hatte ein erweitertes Programm auf dem Atmega328P (5V@16MHz) bereits 
am laufen. Wollte das ganze nun direkt auf den Attiny841 portieren. Ging 
schief, die Leds wurden nicht so angesteuert wie erwünscht. Habe das 
ganze dann kurzer Hand kleiner neugeschrieben. Nur um die Funktion zu 
testen.

Das ging jedoch ebenfalls nicht, gleicher Anzeige wie bei dem vorherigen 
Sketch.

Mein Code sieht in der main.c wie folgt aus.
1
/*
2
* tiny841_ws2812b.c
3
*
4
* Created: 03.12.2015 22:42:09
5
* Author : sschultewolter
6
*/
7
8
#ifndef F_CPU
9
#error F_CPU not defined.
10
#endif
11
12
#include <avr/io.h>
13
#include <util/delay.h>
14
#include "ws2812.h"
15
16
#define GROUP_LEDS
17
18
#define NUM_LEDS  3
19
#define NUM_GROUP  3  // Number of consecutive LEDs with the same value
20
21
struct cRGB rgb[NUM_LEDS];
22
23
int main(void)
24
{
25
  while (1)
26
  {
27
    for(uint8_t i = 0; i < NUM_LEDS; i++)
28
    {
29
      // unset last LED
30
      if(i == 0) rgb[NUM_LEDS-1].r = 0;
31
      else rgb[i-1].r = 0;
32
      
33
      // Set new LED
34
      rgb[i].r = 255;
35
      
36
      // Output at PORTA0
37
      #ifdef GROUP_LEDS
38
      ws2812_setleds_group(rgb, NUM_LEDS, NUM_GROUP);
39
      #else
40
      ws2812_setleds(rgb, NUM_LEDS);
41
      #endif
42
      
43
      _delay_ms(500);
44
    }
45
  }
46
}

In der LIGHT_WS2812 Libary habe ich nur folgende Erweiterung eingebaut
1
void inline ws2812_setleds_group(struct cRGB *rgb, uint16_t numLeds, uint16_t group)
2
{
3
  ws2812_setleds_group_pin(rgb, numLeds, group, (1<<ws2812_pin));
4
}
5
6
void inline ws2812_setleds_group_pin(struct cRGB *rgb, uint16_t numLeds, uint16_t group, uint8_t pinmask)
7
{
8
  ws2812_DDRREG |= pinmask; // Enable DDR
9
  for(uint8_t i = 0; i < numLeds; i++)
10
  {
11
    for(uint8_t groupLed = 0; groupLed < group; groupLed++)
12
    ws2812_sendarray_mask((uint8_t*)rgb, 3, pinmask);
13
  }
14
  // wait 50µs between two ws2812_setleds 
15
  _delay_us(50);
16
}

von Karl M. (Gast)


Lesenswert?

Hallo,

der Attiny841 hat eine andere Ansteuerung der Pins bzgl. In und Out,
sowie das Pin-Routing ist zu beachten, siehe "Alternative Functions of 
Port" und "TOCPMSA1 and TOCPMSA0".

Four I/O memory address locations are allocated for each port, one each 
for the Data Register – PORTx, Data Direction Register – DDRx, Pull-up 
Enable Register – PUEx, and the Port Input Pins – PINx. The Port Input 
Pins I/O location is read only, while the Data Register, the Data 
Direction Register, and the Pull-up Enable Register are read/write. 
However, writing a logic one to a bit in the PINx Register, will result 
in a toggle in the corresponding bit in the Data Register.

von Stefan S. (sschultewolter)


Lesenswert?

Hallo Karl,

danke für die Antwort. Das kann aber nicht das Problem sein. Habe schon 
häufiger Attiny841 für das genutzt. Jedoch bislang wurde immer die 
Funktion ws2812_setleds() genutzt. Sprich, hier hat jede Led fest ihre 
3*8Bit.

Hier sollen sich jedoch je x-Leds den gleichen 3*8Bit Speicher teilen.
Soweit ich das weiß, unterscheided sich der Attiny zu den Atmegas oder 
älternen Attinys darin, dass es ein extra Register für die PullUps gibt. 
Wird hier aber nicht benötigt.

Es geht ja wie gesagt, dass ich die Leds im "Single Modus" (-> 
GROUP_LEDS auskommentiert) betreibe. Einen anderen Pin hatte ich 
Testweise auch schon gewählt.
1
/*
2
* tiny841_ws2812b.c
3
*
4
* Created: 03.12.2015 22:42:09
5
* Author : sschultewolter
6
*/
7
8
#ifndef F_CPU
9
#error F_CPU not defined.
10
#endif
11
12
#include <avr/io.h>
13
#include <util/delay.h>
14
#include "ws2812.h"
15
16
#define GROUP_LEDS
17
18
#ifdef GROUP_LEDS
19
#  define NUM_LEDS    3
20
#  define NUM_GROUP  3  // Number of consecutive LEDs with the same value
21
#else
22
#  define NUM_LEDS  9
23
#endif
24
25
struct cRGB rgb[NUM_LEDS];
26
27
int main(void)
28
{
29
  while (1)
30
  {
31
    for(uint8_t i = 0; i < NUM_LEDS; i++)
32
    {
33
      // unset last LED
34
      if(i == 0) rgb[NUM_LEDS-1].r = 0;
35
      else rgb[i-1].r = 0;
36
      
37
      // Set new LED
38
      rgb[i].r = 255;
39
      
40
      // Output at PORTA0
41
      #ifdef GROUP_LEDS
42
      ws2812_setleds_group(rgb, NUM_LEDS, NUM_GROUP);
43
      #else
44
      ws2812_setleds(rgb, NUM_LEDS);
45
      #endif
46
      
47
      _delay_ms(500);
48
    }
49
  }
50
}

: Bearbeitet durch User
von Stefan S. (sschultewolter)


Lesenswert?

Hier hatte sich ein Fehler eingeschlichen, wieso es auf dem Atmega ging, 
weiß ich nicht
1
  ws2812_sendarray_mask((uint8_t*)rgb, 3, pinmask);

Lösung
1
  ws2812_sendarray_mask((uint8_t*)&rgb[i], 3, pinmask);

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.