Hallo,
Ik probeer een Arduino c++ library voor een LPD8806 RGB ledstrip om te zetten naar C voor avr studio en stoot daarbij op enkele vragen.
1) Is het correct om
uint8_t *pixels;
if(pixels != NULL) free(pixels);en
if(NULL != (pixels = (uint8_t *)malloc(numBytes))) {}om te zetten naar
uint8_t *pixels;
if(pixels) free(pixels);en
if((pixels = (uint8_t *)malloc(numBytes))) {}2) kan ik byte veriabelen vervangen door uint8_t
// Convert separate R,G,B into combined 32-bit GRB color:
uint32_t LPD8806::Color(byte r, byte g, byte b) {
return ((uint32_t)(g | 0x80) << 16) |
((uint32_t)(r | 0x80) << 8) |
b | 0x80 ;
}3) Wanneer ik in onderstaande functie delay(wait) vervang door _delay_ms(wait) krijg in volgende foutmelding...
Error 23 __builtin_avr_delay_cycles expects an integer constant. c:\program files\atmel\atmel studio 6.0\extensions\atmel\avrgcc\3.4.1.95\avrtoolchain\bin\../lib/gcc/avr/4.6.2/../../../../avr/include/util/delay.h 164 28 ledstrip
#include <util/delay.h>// Fill the dots progressively along the strip.
void colorWipe(uint32_t c, uint8_t wait) {
int i;
for (i=0; i < numPixels(); i++) {
setPixelColor(i, c);
show();
delay(wait);
}
}Lucky Luke
Eluke.nl | handgetypt | I'm a poor, lonesome cowboy, with a long, long way to go.
AVR studio 5 doet ook c++ afaik.*
Wat 3 betreft: heb je #define F_CPU opgegeven? (in Hz)
Wat 2 betreft: waarschijnlijk wel, zolang er geen gekke dingen worden gedaan in de constructor van een byte en een byte geen opperators overload.
*EDIT: studio 4 ook, het hangt van de compiler af, en dat is net als bij arduino gCC.
[Bericht gewijzigd door Lucky Luke op (16%)]
pros
Prosper, yop la boum, c'est le roi du macadam (aldus Maurice Chevalier)
malloc() heb ik bij een AVR nog nooit gebruikt. Kan je het niet met een simpele array[] doen?
Wat die _delay_ms(wait) betreft: dat is geen goed idee. Iets als _delay_ms(12.345) kan gerust. De compiler gaat zelf de delay-lus berekenen, en het resultaat bestaat uit enkele regels assembly-code.
Wanneer de delay-tijd tijdens het compileren onbekend is, zit er niets anders op dan _delay_ms(wait) te vertalen naar een gróóte blok assembly-code, die zelf de delay-lus gaat berekenen en bovendien met floats gaat werken.
Zelf doe ik het zo:
void delay_ms(unsigned int ms)
{
for (; ms > 0; ms--) {
_delay_ms(0.99);
}
}
delay_ms(wait);
Dat neemt amper plaats in, en werkt net zo goed.
Op 11 februari 2013 18:54:15 schreef retro man:
1) Is het correct omuint8_t *pixels; if(pixels != NULL) free(pixels);en
if(NULL != (pixels = (uint8_t *)malloc(numBytes))) {}om te zetten naar
uint8_t *pixels; if(pixels) free(pixels);en
if((pixels = (uint8_t *)malloc(numBytes))) {}
Waarom zou je dat willen? Het wordt er niet duidelijker van en het is onnodig. Als je de NULL constante nodig hebt is dat een kwestie van stdlib.h includen.
Malloc op een microcontroller is iets wat ik liever niet doe. Omdat de lengte van je ledstrip waarschijnlijk niet verandert kun je prima met een vaste lengte array af.
Patrick de Zeester
Golden Member
Op 11 februari 2013 18:54:15 schreef retro man:
Hallo,Ik probeer een Arduino c++ library voor een LPD8806 RGB ledstrip om te zetten naar C voor avr studio en stoot daarbij op enkele vragen.
In principe kan je (met wat beperkingen) ook C++ met AVR studio doen (zie ook http://www.nongnu.org/avr-libc/user-manual/FAQ.html#faq_cplusplus en http://avr-cpp-lib.sourceforge.net/). Ik heb de indruk dat de Ardiuino toolchain dezelfde is als die van AVR studio, en dat het enige echte verschil is een library met Arduino specifieke functies (zoals digitalWrite) en de IDE.
Echter de alle code die je hier neergezet hebt lijkt gewoon C te zijn.
1) Is het correct om
uint8_t *pixels; if(pixels != NULL) free(pixels);
Ik mag hopen dat dit niet zo letterlijk in de code staat en dat de pixels pointer nog geïnitialiseerd wordt voor de if statement. De if statement is overigens overbodig omdat de free() functie niets doet als de pointer NULL is.
en
if(NULL != (pixels = (uint8_t *)malloc(numBytes))) {}om te zetten naar
uint8_t *pixels; if(pixels) free(pixels);en
if((pixels = (uint8_t *)malloc(numBytes))) {}
De code van voor en na jouw aanpassing is geldig in zowel C als C++. De getoonde varianten zijn equivalent en zullen naar alle waarschijnlijkheid tot precies dezelfde machine code leiden. De vraag is waarom je dit zou aanpassen.
2) kan ik byte veriabelen vervangen door uint8_t
Dat kan, of je doet een typedef uint_8 byte;
Op 11 februari 2013 20:09:58 schreef Patrick de Zeester:
Ik heb de indruk dat de Ardiuino toolchain dezelfde is als die van AVR studio, en dat het enige echte verschil is een library met Arduino specifieke functies (zoals digitalWrite) en de IDE.
Klopt, zowel AVR studio als Arduino gebruiken GCC-AVR, en de AVR-binutils van GNU onder water.
Oftewel: Als arduino je C++ code vreet, zal AVR studio het ook wel lusten.
Blijft over dat malloc gebruiken in een microcontroller uiterst dubieus is...
[Bericht gewijzigd door blurp op (17%)]
pros
Prosper, yop la boum, c'est le roi du macadam (aldus Maurice Chevalier)
if(pixels != NULL) free(pixels);
// Omzetten naar
if(pixels) free(pixels);
De code van voor en na jouw aanpassing is geldig in zowel C als C++.
Enkel als avr-gcc "NULL" vertaalt naar "0". En waarschijnlijk doet hij dat ook. Maar het lijkt me geen goed idee, dat zomaar voetstoots aan te nemen.
Daarbij komt, zoals je zelf al aangeeft, dat de broncode iets kleiner wordt, maar dat de uiteindelijke machinecode net zo groot blijft.
EricP
mét CE
NULL pointer zijn trouwens best geinig op een 8051. Adres 0 is gewoon een valid stuk RAM... Heb er ooit toch eens 2 dagen naar gezocht... 
roadrunner84
Meep! Meep!
Zover ik weet is free() geheel niet verplicht om de pointer op NULL te zetten!
if(pixels != NULL) free(pixels);
// Omzetten naar
if(pixels) free(pixels), pixels = NULL;void free(void *ptr) kan ptr niet op null zetten, want free heeft het adres van ptr niet.
Verder geeft free geen waarde terug, dus daarmee kun je ptr ook niet op null zetten.
Bedakt voor de hulp iedereen. Dankzij jullie tips heb ik de library ondertussen werkende gekregen. Wel nog met een paar warnings waar jullie mij misschien ook nog kunnen mee helpen.
implicit declaration of function 'memset' [-Wimplicit-function-declaration]
incompatible implicit declaration of built-in function 'memset' [enabled by default]
'b' may be used uninitialized in this function [-Wuninitialized]
'g' may be used uninitialized in this function [-Wuninitialized]
'r' may be used uninitialized in this function [-Wuninitialized]uint32_t Wheel(uint16_t WheelPos)
{
uint8_t r, g, b;
switch(WheelPos / 128)
{
case 0:
r = 127 - WheelPos % 128; //Red down
g = WheelPos % 128; // Green up
b = 0; //blue off
break;
case 1:
g = 127 - WheelPos % 128; //green down
b = WheelPos % 128; //blue up
r = 0; //red off
break;
case 2:
b = 127 - WheelPos % 128; //blue down
r = WheelPos % 128; //red up
g = 0; //green off
break;
}
return(Color(r,g,b));
}volledige bib
/****************************************************
LPD8806 RGB Ledstrip library
****************************************************/
#define F_CPU 8000000UL
#include <avr/io.h>
#include <util/delay.h>
#include <stdlib.h>
uint16_t numLEDs, numBytes;
uint8_t *pixels;
void SPI_init(void){
DDRB = ((1<<DDB3)|(1<<DDB5)|(1<<DDB2)); //spi pins on port b MOSI SCK,SS outputs
SPCR = ((1<<SPE)|(1<<MSTR)|(1<<SPR0)|(1<<CPOL)|(1<<CPHA)); // SPI enable, Master, f/16
}
char SPI_Transmit(char cData){
SPDR = cData;
while(!(SPSR & (1<<SPIF)))
;
return SPDR;
}
void delay_ms(unsigned int ms)
{
for (; ms > 0; ms--) {
_delay_ms(0.99);
}
}
void updateLength(uint16_t n) {
uint8_t latchBytes = (n + 31) / 32;
if(pixels != NULL) free(pixels); // Free existing data (if any)
numLEDs = n;
n *= 3; // 3 bytes per pixel
numBytes = n + latchBytes;
if(NULL != (pixels = (uint8_t *)malloc(numBytes))) { // Alloc new data
memset( pixels , 0x80, n); // Init to RGB 'off' state
memset(&pixels[n], 0 , latchBytes); // Clear latch bytes
} else numLEDs = numBytes = 0; // else malloc failed
// 'begun' state does not change -- pins retain prior modes
}
// Set pixel color from 'packed' 32-bit GRB (not RGB) value:
void setPixelColor(uint16_t n, uint32_t c) {
if(n < numLEDs) { // Arrays are 0-indexed, thus NOT '<='
uint8_t *p = &pixels[n * 3];
*p++ = (c >> 16) | 0x80;
*p++ = (c >> 8) | 0x80;
*p++ = c | 0x80;
}
}
void show(void) {
uint8_t *ptr = pixels;
uint16_t i = numBytes;
while(i--) {
SPI_Transmit(*ptr++);
}
}
uint16_t numPixels(void) {
return numLEDs;
}
// Convert separate R,G,B into combined 32-bit GRB color:
uint32_t Color(uint8_t r, uint8_t g, uint8_t b) {
return ((uint32_t)(g | 0x80) << 16) |
((uint32_t)(r | 0x80) << 8) |
b | 0x80 ;
}
// Chase one dot down the full strip.
void colorChase(uint32_t c, uint8_t wait) {
int i;
// Start by turning all pixels off:
for(i=0; i<numPixels(); i++) setPixelColor(i, 0);
// Then display one pixel at a time:
for(i=0; i<numPixels(); i++) {
setPixelColor(i, c); // Set new pixel 'on'
show(); // Refresh LED states
setPixelColor(i, 0); // Erase pixel, but don't refresh!
delay_ms(wait);
}
show(); // Refresh to turn off last pixel
}
// Fill the dots progressively along the strip.
void colorWipe(uint32_t c, uint8_t wait) {
int i;
for (i=0; i < numPixels(); i++) {
setPixelColor(i, c);
show();
delay_ms(wait);
}
}
//Input a value 0 to 384 to get a color value.
//The colours are a transition r - g -b - back to r
uint32_t Wheel(uint16_t WheelPos)
{
uint8_t r, g, b;
switch(WheelPos / 128)
{
case 0:
r = 127 - WheelPos % 128; //Red down
g = WheelPos % 128; // Green up
b = 0; //blue off
break;
case 1:
g = 127 - WheelPos % 128; //green down
b = WheelPos % 128; //blue up
r = 0; //red off
break;
case 2:
b = 127 - WheelPos % 128; //blue down
r = WheelPos % 128; //red up
g = 0; //green off
break;
}
return(Color(r,g,b));
}
void rainbow(uint8_t wait) {
int i, j;
for (j=0; j < 384; j++) { // 3 cycles of all 384 colors in the wheel
for (i=0; i < numPixels(); i++) {
setPixelColor(i, Wheel( (i + j) % 384));
}
show(); // write all the pixels out
delay_ms(wait);
}
}
// Slightly different, this one makes the rainbow wheel equally distributed
// along the chain
void rainbowCycle(uint8_t wait) {
uint16_t i, j;
for (j=0; j < 384 * 5; j++) { // 5 cycles of all 384 colors in the wheel
for (i=0; i < numPixels(); i++) {
// tricky math! we use each pixel as a fraction of the full 384-color wheel
// (thats the i / strip.numPixels() part)
// Then add in j which makes the colors go around per pixel
// the % 384 is to make the wheel cycle around
setPixelColor(i, Wheel( ((i * 384 / numPixels()) + j) % 384) );
}
show(); // write all the pixels out
delay_ms(wait);
}
}Patrick de Zeester
Golden Member
Voor de memset() functie moet je <string.h> includen.
In de Wheel() functie blijven de r,g en b variabelen ongeïnitialiseerd als WheelPos/128 geen 0, 1, of 2 is. In dat geval is waarde die in deze variabelen terecht komt onvoorspelbaar. Wellicht dat deze situatie nooit voorkomt in dit programma, maar dat weet de compiler niet. De oplossing is om de r, g en b variabelen te initialiseren voor de switch, of een default clause op te nemen in de switch die de r, g en b variabelen een bepaalde waarde geeft.
WheelPos/128 wordt nooit wat anders dan 0, 1, of 2. met een default op te nemen is het probleem idd opgelost.
het memset() probleem zat idd bij <string.h> die niet geinclude was.
bij deze is mijn probleem geheel opgelost. bedankt iedereen.