Nieuws:

Nu in MSM 249 BAAN: Saint-Hilaire * Rügen kustbaan

Hoofdmenu

G.I.P: automatisch schaduwstation zonder wissels

Gestart door conducteur, 09 mei 2012, 21:33:26 PM

conducteur

Als 0x01 werkt in het testprogje van Patrick, wil dat zeggen dat op dat moment enkel 0x01 ingelezen wordt, en geen andere --> geen kortsluitingen. Ik ga Patrick z'n programma nog 7 keer testen, elke keer met een andere knop.
Rian 2-Rail DCC NMBS TPIII
Grote Modeltreinruilbeurs Blankenberge Pasen 2016
Zaal Forum

conducteur

#316


#include <htc.h>
// Config: HS ext Xtal- Watchdogtimer disabled - LVP Disabled
__CONFIG(FOSC_HS & WDTE_OFF & LVP_OFF);
#define _XTAL_FREQ  20000000






void main()
{
    OPTION_REGbits.nRBPU = 1;


    ANSEL = 0;


    ANSELH = 0;




    TRISC = 0x00;
    TRISB = 0xff;      //port B drukknoppen input       




    while (1) {
   PORTC ^= 1 << 4;   // Toggle 5e bit van PORTC (0x10)
   __delay_ms(500);




   switch (PORTB) {   //Zoek welke knop ingedrukt was:
   case 0x01:                      //hier telkens andere waarden invullen.
       PORTC ^= 1 << 5;   // Toggle 6e bit van PORTC (0x20)
       break;
   default:
       0;
   }
    }
}





Alle pinnen van de b-poort worden apart herkend door bovenstaand programma, als je in de switch de juiste waarde invult.  :D
Rian 2-Rail DCC NMBS TPIII
Grote Modeltreinruilbeurs Blankenberge Pasen 2016
Zaal Forum

PeterC

Rian,

Ik kom regelmatig eens piepen naar je vorderingen.  Ik lees niet altijd je code maar ik heb enkele (schoonheids)opmerkingen: laat al die white-space weg (blanco regels maken je programma moeilijker leesbaar - één blanco regel per overgang is meer dan voldoende).  Inspringen: 2 spaties (geen tab!) en je haakjes mooi onder elkaar zodat duidelijk is welk haakje bij welk hoort.

Wat ik niet snap van die High-tech C is dat je nergens een controller moet definiëren; als je naar de ..\include\ directory van de compiler kijkt, staat die vol met definities van iedere mogelijke controller.  Iedere controller heeft andere eigenschappen/registers.
De headerfile 'htc.h' kijkt enkel of het gaat om een gewone pic, een 18... of een ds...
De header 'pic.h' neemt vervolgens 'chip_select.h'.

Daarin staat duidelijk:


/*
* Select device-specific header file
*/


Volgens mij kan je jezelf veel ergernis voorkomen door in het begin van je programma de definitie van je controller op te nemen:


#define _16f887


Dan weet je compiler ten minste dat je met een 16F887 bezig bent.  Anders kan je register aanspreken die in je controller niet voorkomen.  Je compiler trekt zich daar geen snars van aan en compileert je programma (één van de voordelen van C/C++ maar daarom dat ik voor een taal kies waar de compiler kieskeuriger is en minder fouten toe laat).

Blij dat je vorderingen maakt, maar vergeet niet eerst te stappen vooraleer te lopen  ;)



Groetjes, Peter


conducteur

In het begin heb ik in MPlab een nieuw project aangemaakt en daar aangevinkt dat ik die controller wil, en zo weet ie dus wat te doen...
Rian 2-Rail DCC NMBS TPIII
Grote Modeltreinruilbeurs Blankenberge Pasen 2016
Zaal Forum

PeterC

#319
Citaat van: conducteur op 01 november 2013, 19:07:26 PM
In het begin heb ik in MPlab een nieuw project aangemaakt en daar aangevinkt dat ik die controller wil, en zo weet ie dus wat te doen...

Vermoedelijk (hopelijk) weet je compiler dat op die manier, maar een lezer van je programma niet...

[edit]
Een keertje teveel definiëren kan geen kwaad:


#if !defined _16f887
#define _16f887
#endif

Groetjes, Peter


Sattrickske

Rian gebruikt MPLAB, dan hoef je de gebruikte µC inderdaad niet te definiëren in de code; je geeft die enkel mee via de configuratie (select device).  De keuze van de controller wordt mee opgeslagen met je project en als parameter meegegeven aan de compiler...
Voordeel is dat je code makkelijk overdraagbaar is naar andere controllers van dezelfde familie.  Heel veel PICs kun je gewoon uitwisselen...

Maar inderdaad de vele spaties en lege lijnen maken de code moeilijk leesbaar...  Maar opgelet met code formatting, ieder heeft z'n eigen systeem.  Op 't werk wordt er zelfs een verplichte formatting afgedwongen (via automatische controle); als de formattering niet klopt, vliegt de code terug naar de developer.  Dit is nodig om te vermijden dat Source Versioning Control (Subversion, CVS, Git, ...) gek wordt van de verschillen tussen de developers.  En wij doen net het omgekeerde van wat Peter zegt: wel tabs (zeker geen spaties) en het begin haakje altijd op de lijn waar de instructie begonnen is.  Door tabs te gebruiken kan iedereen z'n indent instellen (via de editor) hoe hij/zij dat wil, met spaties kan dit niet meer.  Haakjes (accolades) op dezelfde lijn maken je code compacter en beter leesbaar; en altijd haakjes gebruiken ook wanneer ze niet verplicht zijn, bv.

void main() {
if (state) {
do_something();
} else {
do_something_else();
}
}

De if test heeft in prinicipe geen accolades nodig (omdat er maar één regel volgt); maar wij verplichten de developers om ze toch te zetten, want een veel voorkomende fout is dat men de code nog effe wil aanpassen en regeltje wil toevoegen aan de if test, maar men vergeet dan de accolades en 't is koekenbak (zoals wij in België zeggen)...

Rian's vorderingen komen er stilletjes bij beetje... we weten nu dat de µC correct de software uitvoert (geen verdoken resets) en dat de inputs correct gelezen worden.  Volgende stap: uitgangen verder controleren (2 ledjes hebben we al gedaan).  Laat eerst je schema eens zien en dan kijken we wat we kunnen testen...

Dit zijn ongeveer dezelfde stappen die ik uitvoer wanneer ik m'n twijfels heb over m'n printjes; telkens één onderdeel tegelijk testen en dan later alle stukken 'assembleren' in de code om tot één mooi geheel te komen.

conducteur

Patrick: de ganse beschrijving van dit systeem staat in m'n dossier dat ik heb moeten maken voor het eindwerk vorig jaar, heb dat eens op de server gesmeten:
http://www.treinbaanrian.be/downloads/dossier.pdf
(pin assignments, schema's, principewerking... allemaal in dit heilig dossiertje. :D )
Rian 2-Rail DCC NMBS TPIII
Grote Modeltreinruilbeurs Blankenberge Pasen 2016
Zaal Forum

Sattrickske

Knap dossier(tje)!  Heel proper uitgewerkt!

Om terug bij je controller te komen, ik vermoed dat je nu probeert om één van de NPN transistoren aan te spreken die een relais moeten schakelen? (p. 49)
Ik kan jammer genoeg het schema niet goed zien, de tekening is nogal wazig...

Maar als m'n veronderstelling juist is, heb je al geprobeerd om je relais 'manueel' om te schakelen door effe een kant van het basisweerstandje van de NPN aan de 5V te houden?  Als deze manuele test niet werkt, heb je een probleem met je transistor (een BC547 ?)

conducteur

Alle relais heb ik al kunnen aansturen met de µC... Elke relais inderdaad met een bc 547 aan te sturen, nu zou ik dit doen met een ULN2803, maar dat IC was mij toen onbekend...
Rian 2-Rail DCC NMBS TPIII
Grote Modeltreinruilbeurs Blankenberge Pasen 2016
Zaal Forum

dani

Citaat van: conducteur op 02 november 2013, 00:27:35 AM
nu zou ik dit doen met een ULN2803, maar dat IC was mij toen onbekend...

beginnersfoutje, we maken ze allemaal, ik heb dit IC ook pas recentelijk "ontdekt" en even gevloekt.   Maar wat gebeurd is, is gebeurd :-)
Vooruit kijken en gewoon lekker verder doen is de boodschap.   Komt wel goe !
De kruik is te water gegaan...
De kruik is niet meer.

Sattrickske

Met de BC547 of de ULN2803, maakt niet zoveel uit.  De ULN2803 is compactere versie van de BC547 met flyback diode als je er 8 nodig hebt...
Messtal probeer ik effe te googlen wat ik probeer uit te voeren, heel dikwijls vindt je dan heel wat hints hoe dit opgelost kan worden.  Maar de basis elektronica is steeds verrekte handig en die heb je blijkbaar wel onder de knie.  En als je ergens een oplossing 'vindt', controleer dan steeds de datasheets van de gebruikte componenten; want jammer genoeg levert het internet niet altijd even correcte resultaten.

Kan je nu verder met je software of heb je nog hulp van ons nodig?  Indien ja, laat maar weten welke test je graag zou uitvoeren...

De truc is om niet teveel software ineens te ontwikkelen, probeer steeds met kleine stukjes zoals we hierboven gedaan hebben en voeg ze dan met beetjes samen.  Probeer ook om de belangrijkste blokken (lezen van de input, sturen van de output bv.) in aparte routines onder te brengen.  Later kan je zelfs overwegen om deze onder te brengen in andere modules, zodat je ze snel kan includen in andere projecten.

conducteur

/* **************************************************************************
*    HITECH C for PIC program A_01- 1/11/2013                                        *
•   Author:        Rian De Rous                                          *
****************************************************************************
*      Processor:     PIC16F887                                                                    *
*      Compiler:      HI-TECH C PRO v9.65PL1 Lite                                          *
•   Project: G.I.P. Automatisch schaduwstation zonder wissels                      *
•   Discription: test poort B & stepper motor                                            *
                                                                                      *
************************************************************************* */
#include <htc.h>


// Config: HS ext Xtal- Watchdogtimer disabled - LVP Disabled
__CONFIG(FOSC_HS & WDTE_OFF & LVP_OFF & MCLRE_OFF);
#define _XTAL_FREQ  20000000


void main()
{
    unsigned int teller;
    OPTION_REGbits.nRBPU = 1;   //pull-up b poort disable
    ANSEL = 0;         //analog input disable
    ANSELH = 0;
    TRISC = 0x00;
    TRISB = 0xff;      //port B drukknoppen input       


    while (1)
   {
         PORTC ^= 1 << 5;   // Toggle 5e bit van PORTC (0x10)
         __delay_ms(500);


         switch (PORTB)
           
      {   
         case 0x01:
             teller = 0;
                while (teller != 200)
         {
               PORTC = 0x01;
               __delay_us(1500);
               PORTC = 0x00;
               __delay_us(1500);
               teller++;
         }
     
             break;
             
         case 0x02:
             __delay_ms(50);
             teller = 0;
                while (teller != 400)
         {
               PORTC = 0x01;
               __delay_us(1500);
                PORTC=0x00;
               __delay_us(1500);
               teller++;
         }
             break;
             
         case 0x04:
             __delay_ms(50);
             teller = 0;
                while (teller != 600)
         {
               PORTC = 0x01;
               __delay_us(1500);
                PORTC=0x00;
               __delay_us(1500);
               teller++;
         }
             break;
         
         case 0x08:
              __delay_ms(50);
             teller = 0;
                while (teller != 800)
         {
                PORTC= 0x01;
               __delay_us(1500);
                PORTC=0x00;
               __delay_us(1500);
               teller++;
         }
             break;
             
         case 0x10: 
             __delay_ms(50);
             teller = 0;
                while (teller != 1000)
         {
               PORTC = 0x01;
               __delay_us(1500);
                PORTC=0x00;
               __delay_us(1500);
               teller++;
         }
             break;
             
         case 0x20:
             __delay_ms(50);
             teller = 0;
                while (teller != 1200)
         {
               PORTC = 0x01;
               __delay_us(1500);
                PORTC=0x00;
               __delay_us(1500);
               teller++;
         }
             break;
     
         case 0x40:
             __delay_ms(50);
             teller = 0;
                while (teller != 1400)
         {
               PORTC = 0x01;
               __delay_us(1500);
                PORTC=0x00;
               __delay_us(1500);
               teller++;
         }
             break;
             
             case 0x80:
              __delay_ms(50);
             teller = 0;
                while (teller != 1600)
         {
               PORTC = 0x01;
               __delay_us(1500);
                PORTC=0x00;
               __delay_us(1500);
               teller++;
         }
             break;
         
         default:0;
      }
       }
}

We gaan vooruit, dit werkt... Afhankelijk van welke knop ingedrukt was draait de motor een (paar) toer(en).
Volgende wat ik probeer: de draaizin omkeren.
Rian 2-Rail DCC NMBS TPIII
Grote Modeltreinruilbeurs Blankenberge Pasen 2016
Zaal Forum

Sattrickske

Allez hup, dan ben je nu goed op weg.
Roep maar als we moeten helpen...

Sattrickske

Ben iets te rap geweest met m'n reactie.  Je code zal wel werken, maar bevat een groot gevaar.  Op 't werk noemen we het 'code duplication'; 't is te zeggen dat ik in je code een paar blokken code zie, die steeds terug keren:

               PORTC = 0x01;
               __delay_us(1500);
                PORTC=0x00;
               __delay_us(1500);
               teller++;

Bovenstand blok komt verschillende keren voor in je code en dat is niet goed:
1) Je code wordt er minder leesbaar door
2) Als je hier iets wil wijzigen, moet je dat verschillende keren gaan doen, met meer risico op een dom foutje
3) Het verbruikt meer ROM geheugen

Zulke zaken stop je best in een (sub)routine.

Een tweede opmerking is: gebruik defines om je hardware aan te spreken, als je dan later je hardware wil wijzigen, hoef je enkel maar deze defines aan te passen ipv. van je hele code te moeten doorlopen.

Derde opmerking: je hebt een paar 'gevaarlijke' testen.  Bv.

while (teller != 200)

Dit is levengevaarlijk wanneer je teller door één van de subroutines bokkesprongen gaat/kan maken en je hierdoor bv. plots van 199 naar 201 zou springen of iets dergelijks.  Je while loop gaat deze 'missen' en blijven doorlopen...  Bad practice...
Dit vervang je beter door:

while (teller < 200)


En nog een vierde opmerking (en dan laat ik je gerust ;)): ik vermoed dat je telkens maar één bit van PORTC wil aansturen; maar je zet telkens wel de volledige PORTC.

PORTC = 0x01;

Dit zet alle bits op 0 behalve de eerste.

Betere versie:

PORTC |= (1<<bit);

Bovenstaande zet enkel bit 'bit' aan van PORTC en blijft van de andere bitjes af.  Idem voor het clearen van een bit:

PORTC &= ~(1<<bit);


't Zijn maar details, maar op langere termijn kunnen ze bepalend zijn voor de goede werking van heel je software.

conducteur

#329
Citaat van: Sattrickske op 02 november 2013, 16:17:49 PM
Ben iets te rap geweest met m'n reactie.  Je code zal wel werken, maar bevat een groot gevaar.  Op 't werk noemen we het 'code duplication'; 't is te zeggen dat ik in je code een paar blokken code zie, die steeds terug keren:

               PORTC = 0x01;
               __delay_us(1500);
                PORTC=0x00;
               __delay_us(1500);
               teller++;

Bovenstand blok komt verschillende keren voor in je code en dat is niet goed:
1) Je code wordt er minder leesbaar door
2) Als je hier iets wil wijzigen, moet je dat verschillende keren gaan doen, met meer risico op een dom foutje
3) Het verbruikt meer ROM geheugen

Zulke zaken stop je best in een (sub)routine.


Dat moet ik inderdaad eens uitzoeken hoe dat moet, in het defenitieve programma zal ik dat ook enkele keren moeten gebruiken


Citeer
Een tweede opmerking is: gebruik defines om je hardware aan te spreken, als je dan later je hardware wil wijzigen, hoef je enkel maar deze defines aan te passen ipv. van je hele code te moeten doorlopen.
Dit begrijp ik niet helemaal, bedoel je dat ik toch <htc.h> vervang door die van de controller?
Citeer
Derde opmerking: je hebt een paar 'gevaarlijke' testen.  Bv.

while (teller != 200)

Dit is levengevaarlijk wanneer je teller door één van de subroutines bokkesprongen gaat/kan maken en je hierdoor bv. plots van 199 naar 201 zou springen of iets dergelijks.  Je while loop gaat deze 'missen' en blijven doorlopen...  Bad practice...
Dit vervang je beter door:

while (teller < 200)

Inderdaad, het werkt maar ideaal is het dus niet. In het vervolg dus te vervangen...
Citeer
En nog een vierde opmerking (en dan laat ik je gerust ;) ): ik vermoed dat je telkens maar één bit van PORTC wil aansturen; maar je zet telkens wel de volledige PORTC.

PORTC = 0x01;

Dit zet alle bits op 0 behalve de eerste.

Betere versie:

PORTC |= (1<<bit);

Bovenstaande zet enkel bit 'bit' aan van PORTC en blijft van de andere bitjes af.  Idem voor het clearen van een bit:

PORTC &= ~(1<<bit);


't Zijn maar details, maar op langere termijn kunnen ze bepalend zijn voor de goede werking van heel je software.


Heeft dit dezelfde werking als PORTC|=0x01 (bitje set) & PORTC&=~0x01; (bitje clear)? Ja toch? Dat kende ik toch al ;)
Rian 2-Rail DCC NMBS TPIII
Grote Modeltreinruilbeurs Blankenberge Pasen 2016
Zaal Forum