Nog heel veel meer ontwerptips en domme fouten

High met Henk

Special Member

Ook een leuke hier gehad:

Doorverbind kammetjes voor zekering automaten.
En de isolerende kapjes vallen er wel eens af.

En dan zet iemand ze er weer op.
Leg je dat aan iemand uit als ze er nog op zitten, dat je daarvoor uit moet kijken.

Voel je aan de achterkant ineens koper...

Hebben ze het ding verkeerd gestoken, normaal heb je 2, 3 of 4 sleuven waar de koperstrips met kammen in zitten. Deze had er 2, maar was verkeerd terug gestoken, waardoor voorste sleuf leeg was en eerste strip in 2e gleuf zat, waardoor 2e strip bloot achter het kapje zat..

Had of geluk dat bootje massavrij was of dat de achterste de nul was.
to all newbies: RTFM/D of google eens (p.s. RTFM/D = Read the f*cking manual/datasheet).
Shiptronic

Golden Member

Eerst Afschakelen , Meten, Voelen >:)

2x 1 0 K bruin zwart orange
1x 1 0 0K bruin zwart geel
1x 3 0 0 orange zwart bruin
2x 4 7 00 geel paars rood (in serie)



of zie ik iets over het hoofd?

[Bericht gewijzigd door Shiptronic op 25 februari 2019 21:08:26 (13%)]

Wie de vraag stelt, zal met het antwoord moeten leren leven.
High met Henk

Special Member

Ik voelde geen gezonde spanning toen..
to all newbies: RTFM/D of google eens (p.s. RTFM/D = Read the f*cking manual/datasheet).
ontwerptip: als je losse .c/.h files wilt toepassen in Arduino om een sketch overzichtelijker te maken...

maak er dan .cpp/.h files van. Anders krijg je "undefined reference" voor dingen die toch ècht in de .c staan.

(of zet wat toverspreuken in je .h, https://forum.arduino.cc/index.php?topic=40585.msg296966#msg296966 dan wel rond de include van je .h https://arduino.stackexchange.com/a/949)

c code:
 
// tofu.h file:
#ifndef tofu
#define tofu
void tofu();
#endif
 
//tofu.c
const int bar = 42;
void tofu(){
return bar;
}
 
// in sketch:
#include "tofu.h"
 
int cafe = tofu();
 
 


zal een fout geven.

c code:
 
// tofu.h file:
#ifndef tofu
#define tofu
void tofu();
#endif
 
//tofu.cpp
const int bar = 42;
void tofu(){
return bar;
}
 
// in sketch:
#include "tofu.h"
 
int cafe = tofu();
 
 


zou moeten werken, en

c code:
 
// tofu.h file:
#ifndef tofu
#define tofu
void tofu();
#endif
 
//tofu.c
const int bar = 42;
void tofu(){
return bar;
}
 
// in sketch:
extern "C" {
#include "tofu.h"
}
int cafe = tofu();
 
 

zou ook moeten werken...

Subtiel en kost wat zoekwerk als je er nooit eerder tegenaangelopen bent... " alles staat toch in de .c? heb ik een typevouwtje in de namen soms?"
Blog // Backwards Lightspeed Bus: i*i=-1, so iic=-c.
Of je mikt die Arduino editor waar hij hoort (in de digitale prullenbak) en gebruikt AVR studio, dan heb je een redelijke IDE die hypermoderne dingen kan, zoals debuggen.
Een manager is iemand die denkt dat negen vrouwen in één maand een kind kunnen maken
Jochem

Golden Member

Waar je "undefined reference" vandaan komt is waarschijnlijk dat de main "Arduino Sketch" als C++ wordt gecompileerd (staat ook in 1 van je links) waardoor je symbol names verschillen en je linker het niet meer snapt.

De suggestie van SparkyGSX is wel een goede; zodra je wat serieuzer aan het coden bent kun je beter de Arduino IDE overboord gooien. Ik zou dan vervolgens zelf ook niet kiezen voor AVR studio, maar voor iets dat meer 'algemeen bruikbaar is'.

Ik ben zelf de laatste tijd wat aan het experimenteren met Atom en PlatformIO.
Heb geduld: alle dingen zijn moeilijk voordat ze gemakkelijk worden.
Op 13 april 2019 11:43:49 schreef SparkyGSX:
Of je mikt die Arduino editor waar hij hoort (in de digitale prullenbak) en gebruikt AVR studio, dan heb je een redelijke IDE die hypermoderne dingen kan, zoals debuggen.


Yes, graag. Maar AVR studio draait niet onder Debian. Of OSX. Want ik heb wel vaker software daar gemikt waar het thuishoort... Alleen gooi je daarmee soms je eigen ramen in. (no kun intended >:) En onder OSX moet een goeie IDE te vinden zijn... MPLAB gaat vast ook AVR ondersteunen binnenkort.)

Ik mis het kunnen debuggen wel, en een hele hoop andere dingen...

(Dus dan werk ik met gdb in een terminal. Maar een IDE werkt toch wel fijner dan losse texteditor en terminal met make en gdb...)

Ik heb een Dragon, dus als het moet kan ik gewoon debuggen op AVR. En een STlinkv2 voor de STM32' s, en zelfs ergens een PICkit2, en een Launchpad...

Dus, om ontopic te blijven: tips voor een goeie IDE welkom :)
(ik ga naar SystemWorkbench kijken voor de stm32's, en MPLAB voor PIC)

Enige voordeel van 'duino: makkelijk na te doen voor "Makers" buiten de emsys-hoek. Voor mijn huidige projectje (Lichtwekker. Binnenkort in een Show Your Projectstopic bij u in de buurt!) was dat een overweging. En het draait op alles (Win/Lin/Mac/Web)


(En Jochem heeft gelijk: Arduino sketches zijn c++)

EDIT:

Trouwens ook een leuke rariteit, uit datzelfde project:

c code:
 
//if(autoreel) EVERY_N_SECONDS( 10 ) { nextPattern(); }; // change patterns periodically
 
// hah. the above should work but throws compiler errors unless expressed as:
if (autoreel) {
    EVERY_N_SECONDS( 10 ) {
        nextPattern();  // change patterns periodically 
        };
}
 


Daar staat toch 2x hetzelfde? Waarom zijn die extra { } per sé nodig? (de whitespace maakt niet uit. Althans. Niet getest, maar zou niet uit moeten maken)

(EVERY_N_SECONDS is een macro uit de Fastled library)
Blog // Backwards Lightspeed Bus: i*i=-1, so iic=-c.
Hoeben

Special Member

//if(autoreel) EVERY_N_SECONDS( 10 ) { nextPattern(); }; // change patterns periodically

De expressie voor de IF keuze is toch niet (autoreel) EVERY_N_SECONDS( 10 ) ? Of wel maar dan mis ik een AND of zo?

Bedoel je dit?:
if (autoreel) { EVERY_N_SECONDS( 10 ); nextPattern(); };

[Bericht gewijzigd door Hoeben op 14 april 2019 11:15:07 (92%)]

Ah. Nu zie ik het.
Nee, ik bedoel if (autoreel) { EVERY_N_SECONDS( 10 ) nextPattern(); };
Al is het met extra {} wel duidelijker:

if(autoreel){
EVERY_N_SECONDS( 10 ){
nextPattern();
}
}

Maar, als er maar 1 instructie volgt, hoefden die {} niet. Al mag je ze overal neerzetten of ze nu hoeven of niet.

EVERY_N_SECONDS(10) is echter niet 1 instructie. Maar een macro. Blijkbaar is dat anders?
Blog // Backwards Lightspeed Bus: i*i=-1, so iic=-c.
Een USB naar rs232 ttl gekocht bij de chinees.
Wel met de originele FTDI chip, zodat ik geen chinese CH340 driver moet installeren.
Blijkt de Tx led niet te werken, er zit een via onder de tx led naar de ground.
De voorschakelweerstand van de led staat dus op de voedingsspanning.
De chip trekt het signaal naar de ground.
Ik heb de ground aan de via op de onderkant weg gekrabed en tadaaa, de led knippert.

Altijd goed om eerst die printjes te controleren vooraleer je twijfelt of je mcu nu wel goed werkt...

EVERY_N_SECONDS(10) is echter niet 1 instructie. Maar een macro. Blijkbaar is dat anders?


Yep, eerst gaan je bestanden door een pre-processor waar de macro's worden 'ge-expandeerd', daarna gaan ze door de compiler. Als de macro meerdere instructies oplevert dan kan je dit soort problemen hebben en zal je de {} moeten gebruiken.

Groetjes,
eSe
I am an expert of electricity. My father occupied the chair of applied electricity at the state prison.
Dat is dan alsnog de fout van degene die de macro heeft geschreven. Er is een reden dat je bij macro's vaak veel haakjes ziet die op het eerste gezicht overbodig zijn, dat is om te garanderen dat het expanderen goed gaat, wat de gebruiker ook gedaan heeft. De macro EVERY_N_SECONDS expandeert vrijwel zeker naar meerdere regels code, dus de maker had daar { } omheen moeten zetten.
Een manager is iemand die denkt dat negen vrouwen in één maand een kind kunnen maken
Op 14 april 2019 13:25:42 schreef Lucky Luke:
EVERY_N_SECONDS(10) is echter niet 1 instructie. Maar een macro. Blijkbaar is dat anders?

Stel je schrijft:

code:
#define RESETXY() x = 0; y = 0

en je schrijft dan:

code:
 ... //we zitten in een grote loop
 if (iets) RESETXY ();
 ... // rest grote loop

dan krijgt de echte compiler te zien (na de preprocessor):

code:
 ... //we zitten in een grote loop
 if (iets) x = 0; y = 0;
 ... // rest grote loop

en dat wordt gezien als:

code:
 ... //we zitten in een grote loop
 if (iets) x = 0; 

 y = 0;
 ... // rest grote loop

Nu wordt ALTIJD je y=0 gezet.

Hier zijn diverse oplossingen. in mijn specifieke voorbeeld is natuurlijk:

code:
#define RESETXY() x = y = 0

de makkelijkste.

Maar je zou denken dat gewoon accolades zetten ook zou helpen.
code:
#define RESETXY() {x = 0; y = 0;}

maar de vraag is of de ; achter een "if (iets) {...}" wel mag.
En ook sommige andere oplossingen schijnen op z'n minst in sommige gevallen fout te gaan. Dus de gebruikelijke constructie is:

code:
#define RESETXY() do {x = 0; y = 0;} while (0)

Die is syntactisch gelijk aan een enkele instructie en gedraagt zich (naar ik me heb laten vertellen) in alle gevallen als waar je een gewone functieaanroep zou kunnen zetten.

Dan over EVERY_N_SECONDS... Die zou ik schrijven in C als:
code:
#define EVERY_N_SECONDS(n) for (;;sleep (n))
en volgens mij voldoet dat normaliter precies aan de verwachtingen. Dus ook als dit als body van een if-zonder-haakjes staat, zou het goed moeten gaan.

Zoals sparky zegt {} eromheen werkt vaak, maar net niet altijd. De do ... while (0) truuk werkt net wat vaker.
four NANDS do make a NOR . Kijk ook eens in onze shop: http://www.bitwizard.nl/shop/
ha! Leuk dat zo'n klein vauwtje (van wie laat ik ff in het midden ;):+) een leerzame discussie teweeg brengt :)

@rew: Ik had begrepen dat er wat mis was met x=y=z=0; - achtige constructies...
Maar dat was in de context van DIRA=DIRB=DIRC=0x00; Als DIRB dan 5 bits implementeert en de andere altijd als "1" teruglezen gaat dat fout.
Ik denk dat het ook fout kan gaan als z of y veranderd voordat x is toegewezen... (stel, je zit in een interrupt of in een andere thread aan dezelfde variabelen. Al gaat dat ook fout als je ze elk op een eigen regel toewijst. All wordt dan niet aan x toegewezen wat de interrupt in z heeft gezet. En met do...while(0) gaat dat net zo goed fout). )
Blog // Backwards Lightspeed Bus: i*i=-1, so iic=-c.
Volgens mij wordt bij "a = b = c = 0;" niet de waarde van a, b, en c teruggelezen, maar dat zou wel eens compiler afhankelijk kunnen zijn, net als 1001 andere dingen waarvan we gemakkelijk denken dat ze standaard zijn.

@REW: een ; achter } mag volgens mij altijd; je mag zelfs extra ;'s aan het eind van een regel zetten. Ik zou niet weten in welke situatie die {} in een macro fout zou gaan, maar wellicht bestaat die wel. Tot dusver heb ik er nooit problemen mee gehad, maar ik probeer macro's altijd te beperken tot een enkele statement, anders maak ik er een inline functie van, of een gewone functie, en dan mag de compiler uitzoeken of inlining nuttig is.
Een manager is iemand die denkt dat negen vrouwen in één maand een kind kunnen maken
Als je
code:
#define MYMACRO(x) {this;that} 

doet, dan wordt
code:
if (somecondition)
   MYMACRO (zz);
else 
   somethingelse; 

ineens fout. De ; voor de else mag niet.

Wat het ook al weer precies was moest ik opzoeken. Ik heb hen zojuist hier gevonden.

[Bericht gewijzigd door rew op 14 april 2019 22:23:44 (31%)]

four NANDS do make a NOR . Kijk ook eens in onze shop: http://www.bitwizard.nl/shop/
Volgens mij wordt bij "a = b = c = 0;" niet de waarde van a, b, en c teruggelezen, maar dat zou wel eens compiler afhankelijk kunnen zijn, net als 1001 andere dingen waarvan we gemakkelijk denken dat ze standaard zijn.



Uit de avr-libc FAQ http://nongnu.org/avr-libc/user-manual/FAQ.html


Why is assigning ports in a "chain" a bad idea?

Suppose a number of IO port registers should get the value 0xff assigned. Conveniently, it is implemented like this:
DDRB = DDRD = 0xff;

According to the rules of the C language, this causes 0xff to be assigned to DDRD, then DDRD is read back, and the value is assigned to DDRB. The compiler stands no chance to optimize the readback away, as an IO port register is declared "volatile". Thus, chaining that kind of IO port assignments would better be avoided, using explicit assignments instead:
DDRB = 0xff;
DDRD = 0xff;

Even worse ist this, e. g. on an ATmega1281:
DDRA = DDRB = DDRC = DDRD = DDRE = DDRF = DDRG = 0xff;

The same happens as outlined above. However, when reading back register DDRG, this register only implements 6 out of the 8 bits, so the two topmost (unimplemented) bits read back as 0! Consequently, all remaining DDRx registers get assigned the value 0x3f, which does not match the intention of the developer in any way.


Altijd opletten dus :-) in dit geval met 'volatile' variabelen.

Groetjes,
eSe
I am an expert of electricity. My father occupied the chair of applied electricity at the state prison.
De Avr-libc-faq heeft het fout.

IN "a=b=c=val;" staat er niet "c=val; b=c; a=b;", maar "a= (b= (c=val));". En in de C-standaard staat dat een assignment die gebruikt wordt waar een waarde verwacht wordt de ge-assignde waarde teruggeeft.

In de praktijk:
code:
volatile int a, b, c;

void testit (int val)
{
  a=b=c=val;
}

Met "volatile" geef ik aan dat de variabele zonder waarschuwing tussendoor veranderd kan worden. Dit is ook de manier waarop hardware registers gedefinieerd zijn.

code:
while (!(PINB & 1)); 
zou anders iets worden als: laad PINB in een register, herhaal: test bit 1 in het register of dat al 1 geworden is. Met volatile vertel je de compiler dat ie steeds PINB weer op moet halen alvorens dat ie de test gaat doen.


Met de avr compiler wordt dat:
code:
testit:
        sts c+1,r25
        sts c,r24
        sts b+1,r25
        sts b,r24
        sts a+1,r25
        sts a,r24
        ret
De functie parameter in R24/R25 wordt eerst in c, dan in b en dan in a gezet.

De arm-compiler doet:
code:
testit:
        ldr     r1, .L3
        ldr     r2, .L3+4
        ldr     r3, .L3+8
        str     r0, [r1]
        str     r0, [r2]
        str     r0, [r3]
        bx      lr
Hierbij optimaliseert ie ook nog r1 en r2 weg als ik "static" voor de abc declaratie zet. (*) Merk op dat elders c op het laagste adres wordt gezet, dus weer is het eerst c, dan b, dan a.

En als laatste bij x86 wordt het:
code:
testit:
        movl    %edi, c(%rip)
        movl    %edi, b(%rip)
        movl    %edi, a(%rip)
        ret
met de functie parameter in %edi en gewoon een enkele instructie om de store-naar-memory te regelen.


(*) Dat had ik eerst gedaan, en omdat er in m'n source niets anders bevat was ik bang dat ie misschien toch aannames ging doen van: omdat deze variabelen buiten deze source niet bekend mogen zijn, en ik in deze source kan zien dat ze niet gewijzigd worden, weet ik zeker dat er tussendoor geen wijzigingen zijn. Dat is een foute gedachte van me: die a-b-c variabelen hadden zomaar een hardware register kunnen zijn wat door de hardware veranderd wordt. Ook als er in deze source geen code is die ze verandert!
four NANDS do make a NOR . Kijk ook eens in onze shop: http://www.bitwizard.nl/shop/
Van een eenvoudiger orde: de programmeer/debug aansluiting bereikbaar houden als de behuizing dicht is:



Wel hetzelfde lichtwekker-project. Meer in SyP.
Blog // Backwards Lightspeed Bus: i*i=-1, so iic=-c.
Is dat nou een opbergdoosje met een gat erin :+ . Ook mooi dat er 3 kabels nodig zijn om een lamp op te hangen
Ja, de aftakdoosjes zullen op geweest zijn en toen zal de 'elektricien' zijn lunchdoos ingezet hebben :)
buckfast_beekeeper

Golden Member

Overtollig water kan wel weg.

Ook nog een lasdoos aan de lamp zelf. Grijze kabel wordt daar zwart.
Honing kan je importeren, bestuiving niet.
Jochem

Golden Member

Wat ook nog kan is dat er een lichtsensor in zit, die een iets betere diffusor kon gebruiken, hetgeen met de witte deksel van het lunchtrommeltje is opgelost. En zie ik er nu ook nog een stuk wit papier ofzo bovenop geplakt zitten?

Het hobbybob-gehalte is in ieder geval hoog, want dat zwarte doosje tussen de installatiekabel en het zwarte snoer past ook al niet goed, waardoor er nog een stukkie tape om de kabel moest.
Heb geduld: alle dingen zijn moeilijk voordat ze gemakkelijk worden.
Een China made elektrisch treintje wat voor de toeristen door Leeuwarden rijdt. Had in 2 jaar tijd alweer voor €6000 aan nieuwe accu's nodig gehad volgens de machinist. In de locomotief zit een brandstofmotor die de accu kan opladen. Op de standplaats wordt de accu via 230V en een inverter opgeladen. Zo'n getywrapte verdeeldoos ziet er niet uit. Maar verder wel leuk om te zien! https://citytrainleeuwarden.nl/