Läsa av en digital ingång.

PIC, AVR, Arduino, Raspberry Pi, Basic Stamp, PLC mm.
Användarvisningsbild
newbadboy
Inlägg: 2422
Blev medlem: 16 september 2006, 19:16:28
Ort: Landskrona
Kontakt:

Läsa av en digital ingång.

Inlägg av newbadboy »

Pinsam fråga. men nu har jag suttit snart 2h är trött och ser inte felet. Jag har på ingången kallad BTN en pullup.

I funktionen safety() ska jag stanna kvar så länge knappen är hög men den skiter fullständgit i nivån. Provade att bara läsa knappen (annat bortkommenterat) i while loopen under main och toggla EN4 beroende på BTN men den känner inte av det heller. Känner mig helt skelögd av att kolla på samma grejer hela tiden.

Gäller som vanligt mikroC och 16F18346

Kod: Markera allt

#include "SSD1306driver_lite.h"  // include SSD1306 OLED display driver source code

#define BTN LATC.F5
#define OUT LATC.F4
#define EN4 LATC.F7
#define EN3 LATB.F4
#define EN2 LATC.F1
#define EN1 LATA.F2
#define test LATC.F4

#define SSD1306_SOFT_I2C
#define SSD1306_128_64

char PrintOut[5];
float Ptot, Temp, TempF, TempOut, Vbat, Adc1, Adc2, Adc3, Adc4;



// Software I2C connections
sbit Soft_I2C_Scl           at RB7_bit;
sbit Soft_I2C_Sda           at RB5_bit;
sbit Soft_I2C_Scl_Direction at TRISB7_bit;
sbit Soft_I2C_Sda_Direction at TRISB5_bit;
// End Software I2C connections


void NTC_Lookup(){
               TempOut=20;
            if(511<Temp)
               TempOut=25;
            if(559<Temp)
               TempOut=30;
            if(604<Temp)
               TempOut=35;
            if(646<Temp)
               TempOut=40;
            if(646<Temp)
               TempOut=45;
            if(686<Temp)
               TempOut=50;
            if(722<Temp)
               TempOut=55;
            if(755<Temp)
               TempOut=60;
            if(785<Temp)
               TempOut=65;
            if(812<Temp)
               TempOut=70;
            if(836<Temp)
               TempOut=75;
            if(858<Temp)
               TempOut=80;
            if(875<Temp)
               TempOut=85;
        //    if(893<Temp)
        //       TempOut=90;
         //   if(908<Temp)
         //      TempOut=95;
         /*   if(922<Temp)
               TempOut=100;
            if(934<Temp)
               TempOut=105;
            if(944<Temp)
               TempOut=110;
            if(953<Temp)
               TempOut=115;
            if(961<Temp)
               TempOut=120;
            if(968<Temp)
               TempOut=125;
           */
            TempF=(TempOut*1.8)+32;
                    
}


void Safety(){
            if(Temp>908){             //95grader
                     SSD1306_ClearDisplay();
                     SSD1306_GotoXY(1, 1);
                     SSD1306_Print("SYSTEM OVERHEATED!!");
                     SSD1306_GotoXY(1, 16);
                     SSD1306_Print("Cooling, press Btn! ");
                     SSD1306_Display();
                     EN1=0;
                     EN2=0;
                     EN3=0;
                     EN4=0;
                     while((Temp>908)||(BTN==1)){
                           Temp=ADC_Read(4);
                          //wait to cool down
                          }
                     EN1=1;
                     EN2=1;
                     EN3=1;
                     EN4=1;
                     SSD1306_ClearDisplay();
              }
             
             Vbat=ADC_Read(5);
             if((Vbat>647)||(Vbat<540)){//4,75V-5,8V
                EN1=0;
                EN2=0;
                EN3=0;
                EN4=0;
                SSD1306_ClearDisplay();
                Delay_ms(100);
                if(Vbat>647){
                   SSD1306_TextSize(1);
                   SSD1306_GotoXY(1, 1);
                   SSD1306_Print("HIGH VOLTAGE, press Btn!");
                   SSD1306_Display();
                   while((Vbat>647)||(BTN==0)){
                       //Wait
                       Vbat=ADC_Read(5);
                   }    
                  }
                if(Vbat<540){
                   SSD1306_ClearDisplay();
                   SSD1306_TextSize(1);
                   SSD1306_GotoXY(1, 1);
                   SSD1306_Print("LOW VOLTAGE, press Btn!");
                   SSD1306_Display();
                   while((Vbat<540)||(BTN==1)){
                       //Wait
                       Vbat=ADC_Read(5);
                   }
                  }
                EN1=1;
                EN2=1;
                EN3=1;
                EN4=1;
                SSD1306_ClearDisplay();
                }

                if((ADC1>3200)||(ADC1>3200)||(ADC1>3200)||(ADC1>3200)){
                    Delay_ms(1000);
                    SSD1306_ClearDisplay();
                    Adc1=ADC_Read(16);
                    Adc1=Adc1*0.006;
                    Adc2=ADC_Read(18);
                    Adc2=Adc2*0.0049;
                    Adc3=ADC_Read(14);
                    Adc3=Adc3*0.0039;
                    Adc4=ADC_Read(22);
                    Adc4=Adc4*0.0056;
                    if(Adc1>3200){
                      EN1=0;
                      SSD1306_TextSize(2);
                      SSD1306_GotoXY(1, 1);
                      SSD1306_Print("CH1 OVERLOAD, press Btn!");
                      while(BTN!=0){
                          //wait
                          }
                      }
                     if(Adc2>3200){
                      EN2=1;
                      SSD1306_TextSize(2);
                      SSD1306_GotoXY(1, 1);
                      SSD1306_Print("CH2 OVERLOAD, press Btn!");
                      while(BTN!=0){
                          //wait
                          }
                      }
                     if(Adc3>3200){
                      EN3=0;
                      SSD1306_TextSize(2);
                      SSD1306_GotoXY(1, 1);
                      SSD1306_Print("CH3 OVERLOAD, press Btn!");
                      while(BTN!=0){
                          //wait
                          }
                      }
                      if(Adc4>3200){
                      EN4=0;
                      SSD1306_TextSize(2);
                      SSD1306_GotoXY(1, 1);
                      SSD1306_Print("CH4 OVERLOAD, press Btn!");
                      while(BTN!=0){
                          //wait
                          }
                      }
                    EN1=1;
                    EN2=1;
                    EN3=1;
                    EN4=1;
                    SSD1306_ClearDisplay();
                    }

}

void Adc_Read_All(){
           Temp=ADC_Read(4);    //ANA4
           NTC_Lookup();


           Vbat=ADC_Read(5);    //ANA5
           Vbat=Vbat*0.0088;

           Adc1=ADC_Read(16);   //CH1
           if(Adc1<20)          //filter
              Adc1=0;
           Adc1=Adc1*0.0063;
           
           Adc2=ADC_Read(18);   //CH2
           if(Adc2<20)
              Adc2=0;
           Adc2=Adc2*0.0052;
           
           Adc3=ADC_Read(14);   //CH3
           if(Adc3<20)
              Adc3=0;
           Adc3=Adc3*0.0041;
           
           Adc4=ADC_Read(22);   //CH4
           if(Adc4<20)
              Adc4=0;
           Adc4=Adc4*0.0059;
           
           Ptot=Vbat*(Adc1+Adc2+Adc3+Adc4);
           
}



Battery_Bar(){

        if(Ptot<=0.2){
          SSD1306_FillRoundRect(94, 2, 7, 6, 1);
          SSD1306_DrawRoundRect(90, 7, 15, 29, 2);
          SSD1306_FillRect(92, 9, 11, 7);
          SSD1306_FillRect(92, 18, 11, 7);
          SSD1306_FillRect(92, 27, 11, 7);
          SSD1306_Display();
          }
        if(Ptot>0.2){
           SSD1306_Color = false;
           SSD1306_FillRect(92, 9, 11, 7);
           SSD1306_Display();
           SSD1306_Color = true;
           SSD1306_FillRect(92, 9, 11, 7);
           }
}

       
void Display_Out(){
           
           
           
           SSD1306_Color = 1;
           SSD1306_TextSize(1);
           
           Battery_Bar();

           SSD1306_GotoXY(1, 1);
           SSD1306_Print("SYSTEM");
           
           SSD1306_GotoXY(1, 36);
           SSD1306_Print("OUTPUT");
           
           SSD1306_GotoXY(25, 11);
           SSD1306_Print("V");
           sprintf(PrintOut, "%.2f", Vbat);
           SSD1306_GotoXY(1, 11);
           SSD1306_Print(PrintOut);
           
           SSD1306_GotoXY(57, 11);
           SSD1306_Print("C");
           sprintf(PrintOut, "%.0f", TempOut);
           SSD1306_GotoXY(45, 11);
           SSD1306_Print(PrintOut);
           
           if(TempF>=100){
              SSD1306_GotoXY(64, 20);
              SSD1306_Print("F");
              }
           if(TempF<100){
              SSD1306_GotoXY(64, 20);
              SSD1306_Print(" ");
              }
           SSD1306_GotoXY(57, 20);
           SSD1306_Print("F");
           sprintf(PrintOut, "%.0f", TempF);
           SSD1306_GotoXY(45, 20);
           SSD1306_Print(PrintOut);
           
           
           
           

           if(Ptot<0.1){
              SSD1306_GotoXY(19, 20);
              SSD1306_Print("0");
              }
           SSD1306_GotoXY(25, 20);
           SSD1306_Print("W");
           sprintf(PrintOut, "%.1f", Ptot);
           SSD1306_GotoXY(1, 20);
           SSD1306_Print(PrintOut);
           
           SSD1306_GotoXY(1, 46);
           SSD1306_Print("Ch1");
            if(ADC1>0.1){
              SSD1306_GotoXY(53, 46);
              SSD1306_Print("<");
              }
           if(ADC1<0.1){
              SSD1306_GotoXY(53, 46);
              SSD1306_Print(" ");
              }
           SSD1306_GotoXY(48, 46);
           SSD1306_Print("A");
           sprintf(PrintOut, "%.3f", Adc1);
           SSD1306_GotoXY(23, 46);
           PrintOut[4]=0;
           SSD1306_Print(PrintOut);

           SSD1306_GotoXY(1, 56);
           SSD1306_Print("Ch2");
            if(ADC2>0.1){
              SSD1306_GotoXY(53, 56);
              SSD1306_Print("<");
              }
           if(ADC2<0.1){
              SSD1306_GotoXY(53, 56);
              SSD1306_Print(" ");
              }
           SSD1306_GotoXY(48, 56);
           SSD1306_Print("A");
           sprintf(PrintOut, "%.3f", Adc2);
           SSD1306_GotoXY(23, 56);
           PrintOut[4]=0;
           SSD1306_Print(PrintOut);

           SSD1306_GotoXY(76, 56);
           SSD1306_Print("Ch3");
           if(ADC3>0.1){
              SSD1306_GotoXY(69, 56);
              SSD1306_Print(">");
              }
           if(ADC3<0.1){
              SSD1306_GotoXY(69, 56);
              SSD1306_Print(" ");
              }
           SSD1306_GotoXY(123, 56);
           SSD1306_Print("A");
           sprintf(PrintOut, "%.3f", Adc3);
           SSD1306_GotoXY(98, 56);
           PrintOut[4]=0;
           SSD1306_Print(PrintOut);
           
           SSD1306_GotoXY(76, 46);
           SSD1306_Print("Ch4");
            if(ADC4>0.1){
              SSD1306_GotoXY(69, 46);
              SSD1306_Print(">");
              }
           if(ADC4<0.1){
              SSD1306_GotoXY(69, 46);
              SSD1306_Print(" ");
              }
           SSD1306_GotoXY(123, 46);
           SSD1306_Print("A");
           sprintf(PrintOut, "%.3f", Adc4);
           SSD1306_GotoXY(98, 46);
           PrintOut[4]=0;
           SSD1306_Print(PrintOut);
           
           SSD1306_Display();

}


Init_main(){
       OSCCON1=0B00000001;
       OSCFRQ=0b00000110;         // set internal oscillator to 16MHz
       OSCTUNE=0b00000000;

       ANSELA=0b00110000;         // configure all PORTS
       ANSELB=0b01000000;
       ANSELC=0b00000101;
       TRISA=0b00110000;
       TRISB=0b01000000;
       TRISC=0b00100101;

  //     delay_ms(1000);     // wait a second
       Soft_I2C_Init();  // initialize I2C communication
       
       SSD1306_Begin(SSD1306_SWITCHCAPVCC, SSD1306_I2C_ADDRESS);
       SSD1306_Display();
       delay_ms(2000);
       SSD1306_ClearDisplay();   // clear the buffer

  //     ADC_Init();

       EN1=1;
       EN2=1;
       EN3=1;
       EN4=1;
       
       Ptot=0.1;
       Battery_Bar();

}


// main function
void main(){
     Init_main();
     while(1){
         ADC_Read_All();
         Display_Out();
         Safety();
     }
}
Användarvisningsbild
sodjan
EF Sponsor
Inlägg: 43129
Blev medlem: 10 maj 2005, 16:29:20
Ort: Söderköping
Kontakt:

Re: Läsa av en digital ingång.

Inlägg av sodjan »

Som vanligt, gör ett minimalt program som enbart känner av knappen
och ställer en LED. Fungerar inte det, posta det. Ingen orkar plöja
igenom över 400 rader kod enbart för just det...
Användarvisningsbild
newbadboy
Inlägg: 2422
Blev medlem: 16 september 2006, 19:16:28
Ort: Landskrona
Kontakt:

Re: Läsa av en digital ingång.

Inlägg av newbadboy »

Plockat bort en massa nu. Utgången EN4 ligger låg hela tiden..

Kod: Markera allt

#include "SSD1306driver_lite.h"  // include SSD1306 OLED display driver source code

#define BTN LATC.F5
#define OUT LATC.F4
#define EN4 LATC.F7
#define EN3 LATB.F4
#define EN2 LATC.F1
#define EN1 LATA.F2
#define test LATC.F4

#define SSD1306_SOFT_I2C
#define SSD1306_128_64

char PrintOut[5];
float Ptot, Temp, TempF, TempOut, Vbat, Adc1, Adc2, Adc3, Adc4;



// Software I2C connections
sbit Soft_I2C_Scl           at RB7_bit;
sbit Soft_I2C_Sda           at RB5_bit;
sbit Soft_I2C_Scl_Direction at TRISB7_bit;
sbit Soft_I2C_Sda_Direction at TRISB5_bit;
// End Software I2C connections


Init_main(){
       OSCCON1=0B00000001;
       OSCFRQ=0b00000110;         // set internal oscillator to 16MHz
       OSCTUNE=0b00000000;

       ANSELA=0b00110000;         // configure all PORTS
       ANSELB=0b01000000;
       ANSELC=0b00000101;
       TRISA=0b00110000;
       TRISB=0b01000000;
       TRISC=0b00100101;

  //     delay_ms(1000);     // wait a second
       Soft_I2C_Init();  // initialize I2C communication
       
       SSD1306_Begin(SSD1306_SWITCHCAPVCC, SSD1306_I2C_ADDRESS);
       SSD1306_Display();
       delay_ms(2000);
       SSD1306_ClearDisplay();   // clear the buffer

  //     ADC_Init();

       EN1=1;
       EN2=1;
       EN3=1;
       EN4=1;
       
       Ptot=0.1;
     //  Battery_Bar();

}


// main function
void main(){
     Init_main();
     while(1){
      //   ADC_Read_All();
      //   Display_Out();
      //   Safety();
      
      if(BTN==1)
      EN4=1;
      if(BTN==0)
      EN4=0;
      
      
      
      
      
     }
}
H.O
Inlägg: 5679
Blev medlem: 19 mars 2007, 10:11:27
Ort: Ronneby

Re: Läsa av en digital ingång.

Inlägg av H.O »

Kod: Markera allt

#define BTN LATC.F5
Nu är jag ingen fena på C men det där funkar nog inte så bra om syftet är att BTN skall vara en ingång, då måste du läsa PORT-registret.
Användarvisningsbild
Wedge
Inlägg: 1026
Blev medlem: 8 juli 2012, 17:33:33

Re: Läsa av en digital ingång.

Inlägg av Wedge »

När variabler ligger i hårdvaruregister måste man vanligtvis ha med "volatile" i deklarationen, annars vet inte kompilatorn om att man måste läsa i hårdvaran hela tiden för att se en ändring i BTN. Kodmässigt ser kompilatorn ingen ändring av BTN, och då kan den få för sig att optimera bort jämförelsen.
Samma sak med variabler som ändras i en interruptrutin, och testas av kod i annat scope.
Användarvisningsbild
Icecap
Inlägg: 26093
Blev medlem: 10 januari 2005, 14:52:15
Ort: Aabenraa, Danmark

Re: Läsa av en digital ingång.

Inlägg av Icecap »

LAT är utgångsregistret och avspeglar ALDRIG input! Använd PORT!
Användarvisningsbild
Klas-Kenny
Inlägg: 11277
Blev medlem: 17 maj 2010, 19:06:14
Ort: Växjö/Alvesta

Re: Läsa av en digital ingång.

Inlägg av Klas-Kenny »

Wedge skrev:När variabler ligger i hårdvaruregister måste man vanligtvis ha med "volatile" i deklarationen, annars vet inte kompilatorn om att man måste läsa i hårdvaran hela tiden för att se en ändring i BTN. Kodmässigt ser kompilatorn ingen ändring av BTN, och då kan den få för sig att optimera bort jämförelsen.
Samma sak med variabler som ändras i en interruptrutin, och testas av kod i annat scope.

"LATC.F5" lär vara deklarerad med volatile.
Använder man sen #define BTN LATC.F5 så blir även BTN volatile då define bara gör en ren textersättning i preprocessorn.
Användarvisningsbild
newbadboy
Inlägg: 2422
Blev medlem: 16 september 2006, 19:16:28
Ort: Landskrona
Kontakt:

Re: Läsa av en digital ingång.

Inlägg av newbadboy »

OK nu funkar det.

Alltså jag jag trodde jag förstod skillnaden mellan LAT och PORT.

Jag hade definat allt som port innan men fick inte I2C att skicka ngt vettigt. Den skickade bara en massa rappakalja. Pratade med en som förklarade att skriver man till PORT så "togglar" man alla bitar samtidigt. Jag har ju i2c på port B men också andra pinnar som används. Så det som hände var att jag ändrade alla bitar och försökte skicka i2c samtidigt.

Ändrar jag då till LAT så påverkar jag endast den biten jag vill ovh inte hela porten. Lite lulligt förklarat men jag måste ha missförtått honom
Användarvisningsbild
Icecap
Inlägg: 26093
Blev medlem: 10 januari 2005, 14:52:15
Ort: Aabenraa, Danmark

Re: Läsa av en digital ingång.

Inlägg av Icecap »

Det är delvist rätt. Om du skriver till ett PORT-register kommer utgånger att ändra sig - men R-M-W problematiken kan ställa till det.

Ska man ändra en portpinne som är utgång är det bäst att skriva till LAT-registret.

R-M-W är Read-Modify-Write och essentiellt är det så att om man vill växla en bit på porten sker det som följer:
1: Porten läsas som en byte. (READ)
2: Bit'en växlas i den lästa byte. (MODIFY)
3: Byten skrivas tillbaka till porten. (WRITE)

Problemet är att har man fler ändringar direkt efter varandra OCH en kapacitiv belastning på en eller fler portpinnar kommer läsningen att avspegla de verkliga nivåer och om man t.ex. har lagt en pinne hög men att kondingen på utgången (t.ex. MOSFET Gate) inte har hunnit med upp kommer den att läsas som '0'.

Sedan modifieras byten och skrivs tillbaka - men nu är det alltså sket en oavsiktlig ändring så att pinnen som skulle gå mot '1' och INTE skulle ändras klappas till '0'.

Detta sker om man använder PORT-registret och det går ganska fel. Har man inte kondensatoreffekt men kanske LED utan seriemotstånd (eller annan överbelastning) på en eller fler pinnar kan man få samma problem.

Alltså "ska" man göra de bit-manipulationer för utgångar på LAT-registren där de finns.
Användarvisningsbild
newbadboy
Inlägg: 2422
Blev medlem: 16 september 2006, 19:16:28
Ort: Landskrona
Kontakt:

Re: Läsa av en digital ingång.

Inlägg av newbadboy »

Amen va fanken. Precis när jag trodde jag lärt mig ngt kommer ett nytt bud. Får bli snickare istället.

Tack för svar
Användarvisningsbild
Swech
EF Sponsor
Inlägg: 4686
Blev medlem: 6 november 2006, 21:43:35
Ort: Munkedal, Sverige (Sweden)
Kontakt:

Re: Läsa av en digital ingång.

Inlägg av Swech »

Det är ett PIC relaterat problem
Andra processorer har interna buffertar så då man läser tillbaks
vad porten har för utgångsvärde så är det förväntat värde man får tillbaks,
inte ett återläst värde påverkat från yttervärlden.

Sedan så bör du böja använda dig av konstanter i programmet
Det blir hopplöst att underhålla program som är fulla med kryptiska siffror
som är självklara då du skrev det hela men inte 6 månader senare...

Se det som så att ditt program skall behandla data som du definierar på ett annat ställe
än uppe i koden. Koden skall jobba med konstanter och variabler.

Swech
Användarvisningsbild
newbadboy
Inlägg: 2422
Blev medlem: 16 september 2006, 19:16:28
Ort: Landskrona
Kontakt:

Re: Läsa av en digital ingång.

Inlägg av newbadboy »

Du förutsåg min nästa fråga ang om andra tillverkare har samma egenskap. Bra ide med konstanter. Ska prova fixa till det men inte säkert rommet räcker :)
Användarvisningsbild
Icecap
Inlägg: 26093
Blev medlem: 10 januari 2005, 14:52:15
Ort: Aabenraa, Danmark

Re: Läsa av en digital ingång.

Inlägg av Icecap »

Om man använder t.ex. 10 en del ställen OCH att de alla refererar till samma värde kan man definiera värdet ETT ställe:
#define EtVisstVärde 10

Om man sedan (vilket definitiv sker) behöver t.ex. 10+1 eller 10-1 anger man:
EttVisstVärde + 1; eller EttVisstVärde - 1;

På det vis händer det alltid ihop och det blir ingen ställen där man glömde ändra något.

Jag har ett gammalt men ytterst aktuellt exempel:
Jag programmerade en styrning som körde 3 st keramikugnar på en klinkerfabriks lab.
Ugnarna skulle köra efter en kurva typ 35°C/timmen till 1100°C, hålla temperaturen i 30 minuter, 25°C/timmen till 35°C.

Man skrev in en kurva i biblioteket och kunde sedan starta en ugn o låta den köra en given kurva.
Alla ugnar körde oberoende av varandra såklart.

Jag löste det vid att definiera:
#define Library_Curves 10; // Antal bibliotekskurver

Alla scanninger av kurvor, inskrivning osv. använde detta värde som bas.

Ett antal år senare kom fabriken åter o frågade han jag jobbade för om det gick att utöka antal kurvor i biblioteket. Han ville kolla på det - och en kommentar som jag hade skrivit gav att det var plats till 401 st.

Han ändrade definitionen från 10 till 25, kompilerade skiten, brände EPROM - och väntade ett par dagar mer. Då kontaktade han dom o berättade att han hade lyckats pressa in 25 st men att det hade tagit alla dagar i beslag...

Och det fungerade såklart prickfritt.
Senast redigerad av Icecap 11 september 2019, 16:10:33, redigerad totalt 1 gång.
Användarvisningsbild
newbadboy
Inlägg: 2422
Blev medlem: 16 september 2006, 19:16:28
Ort: Landskrona
Kontakt:

Re: Läsa av en digital ingång.

Inlägg av newbadboy »

Grymt.
Användarvisningsbild
Swech
EF Sponsor
Inlägg: 4686
Blev medlem: 6 november 2006, 21:43:35
Ort: Munkedal, Sverige (Sweden)
Kontakt:

Re: Läsa av en digital ingång.

Inlägg av Swech »

Det tar inte mer plats med konstanter
  • if(511<Temp)
    TempOut=25;
    if(559<Temp)
    TempOut=30;
    if(604<Temp)
    TempOut=35;
Dina siffror 511,559 och 604 är redan konstanter men angivna med siffror
om du skriver
#define NTC_25 511
och längre ned skriver
if(NTC_25<Temp)
TempOut=25;
så tar det exakt samma plats men blir lättare att läsa
Nu är mina C kunskaper inte på topp så om definitionen är felaktig så är det principen jag är ute efter...


Swech
Skriv svar