Projekt spínacího zařízení v závislosti na vstupním napětí

Ahoj,
začínám(tedy chtěl bych začít :smiley:) s programováním PIC. Na škole jsme sice jejich programování měli, ale to jejiž několik let zpět :slight_smile:. Proto bych měl několik otázek . Cíl mého snažení by měl být “převodník” který bude spínat jednotlivé výstupy podle toho jaké napětí(rozmezí od-do) bude na vstupu.

Takže:

  1. Je možné vůbec něco podobného s PIC provéct ? Jde mi hlavně o to určení rozmezí napětí(např. 0,5V - 1V = výstup 1 , 1 - 1,5V = výstup 2 atd…)

  2. Bude k tomu stačit např. PIC12F683-I/P(200ns Instruction Execution, 3584bytes Flash program memory (2048x14words), 128bytes RAM, 256byte EEPROM, 6 I/O, 4 ADC 10bit, 2x8bitTimer &16bitTimer , PWM, WDT, ICSP, 8 pin DIL). Vstup by měl být jen 1(napětí) a výstupů 5.

  3. Mohli by jste mi doporučit nějaký SW(zda existuje něco k simulaci-bez HW) ? Případně jaký překladač(pro mě asi nejjednodušší řešení)

Díky za odpověď .

:arrow_right: administrator: přesunuto z "Programátory"

:arrow_right: administrator: přejmenováno z "Všeobecné informace o PIC :slight_smile:"

Omlouvám se za špatnou sekci… chtěl jsem to zařadit do sekce : Microchip

  1. Ano je to jednoduchý program.
  2. Nebude stačit, GP3 je pouze vstup.
  3. Tady

Ok…
takže jsem se rozhodl, že použiju raději překladač z C(nalezl jsem mikroC) .
Dále tedy vezmu PIC PIC18F1220-I/P , ten už by měl mít dost IO :slight_smile:

[code]unsigned int napeti;
unsigned int i;

void main() {
TRISA = 0xFF; // PORTA je vstup
TRISB = 0x00; // PORTB je vystup
ADCON1 = 00000001; // AN0 je vstup

i=0;
do {
i++;
napeti = i;//ADC_Read(1); // “Jako” hodnota…
if (napeti>=1 && napeti<3){
PORTB = 0x01; //Stav 1
}

if (napeti>=3 && napeti<6){
    PORTB = 0x02; //Stav 2
}

if (napeti>=6 && napeti<9){
    PORTB = 0x03; //Stav 3
}

if (napeti>=9 && napeti<12){
    PORTB = 0x04; //Stav 4
}

if (napeti>=12 && napeti<15){
    PORTB = 0x05; //Stav 5
}

if(i==15){
 i=0;
}

} while(1);
}[/code]

A takhle napsané ti to funguje ?

Osobne by som asi dal switch -case… Ved ked ssa dotoho pusti…uvidi ako to beha :smiley:

No funguje… v simulátoru(resp. při krokování) ano.
Funkčnost prozatím nemohu ověřit(PICKIT II je na cestě a MCU budu teprve kupovat).

Switch možná použiju,ale dneska jsem to nainstaloval a tak tam mám jisté problémy :smiley:

Jen si nejsem jist s definicí “ADCON1 = 00000001” zda jsem to z datasheetu pochopil správně :smiley:(stejně počítám že to fungovat samozřejmě na poprvé nebude…)

1, Fungovat to nebude, lebo je zle inicializovany ADC. Treba siahnut do ADCON0 az ADCON2. Naschval nepisem ako, nech si to NoBody skusi dobre prezriet, ak nebudes vediet, tak to nejako doklepeme.
Dalej, vysledok AD prevodu netreba tahat z nejakej obskurnej funkcie ADC_Read(1);, nakolko k zdrojaku nie su nalinkovane neijake .h subory, predpokladam, ze prekladac vyhodi chybu, ze taku funkciu nepozna. Vysledok AD prevodu sa da normalne vycitat z ADRESH a ADRESL registrov.

2, Lepsie nez MikroC pre PIC18 je jednoznacne pouzitie kombinacie MPLAB+MCC18 (C18 prekladac vo free Lite verzii). Je to rovno od Microchipu, podporuje to vsetky mozne nastroje od Microchipu a hlavne to nie je nejake limitovane demo, ale plnohodnotny a seriozny vyvojovy nastroj.

dobre prezriet by sis to měl ty jaromíre. :slight_smile:
Funkce ADC_Read(1); je zaremovaná a tudíš nefunkční.
Jako vstupní napětí se používá načítání registru napeti a jeho hodnota je použita při rozhodování který pin sepnout.

Alespoň tak jsem to z výpisu pochopil já.

Tak on tan program zatím nic společnýho s měřením pomocí ADC nemá, tudíž máte pravdu oba :slight_smile: Navíc rozhodně není kompletní, musí mít minimálně 1 hlavičkovej soubor (s definicema pokud nepoužívá přímo adresy).

jaromir:
Jak jsem tedy na to koukal, tak by měl být(snad :smiley:):
ADCON0 : 0b00000011
ADCON1 : 0b01111110
ADCON2 : 0b00110111

Sice nevim jaké používáme zarovnání binární hodnoty(tedy v tom co znám - 0b00000010 = 2) ale to se dá vždy přehodit. Takže jsem nastavil 0-left justifed . TAD neznám, ale tak zkusim 16. Něco jiného bude až budu mít MCU u sebe a budu moct s tím experimentovat :slight_smile: . Takhle to střílím od oka což vzhledem k tomu že MCU jsem programoval ve škole cca 6h celkem tak vycházím z metody pokus-omyl :smiley:

Ta funkce ADC_Read(1) byla v jejich ukázkovém kodu, tak jsem předpokládál že “to nějak” bude fungovat “samo” :smiley:

MPLAB+MCC18: Nainstalováno ale zdá se mi to celé nějak nepřehledný. Pravda moc času jsem tomu nedal…takže uvidim do budoucna, ale prozatím bych se zdržel u MikroC.

Petr:
Původně jsem počítal s tím, že bych tam nechal jen to “ADC_Read(1)” . napeti jsem zavedl protože v MikroC nevim jak simulovat hodnotu z něj a tak k odzkoušení podmínek if(i když není co zkoušet :smiley:) jsem zavedl napeti = i++

piityy:
Při překladu kompilátor nic nehlásí tak vycházím s tím, že to snad bude fungovat :smiley: . Ale když na to koukám, tak asi ne …

Vyzera to na prvy pokus dobre, ale styri veci by som podotkol:
1, Bit 1 v ADCON0 je bit GO_DONE - ten je zbytocne anstavovat v inicializacii. ten treba nastavit pred meranim, resp. nim sa spusta meranie. Nastavis bit a potom cakas v slucke, kym sa nezhodi naspat do nuly, vtedy mas vysledok prevodu v ADRESH a ADRESL registroch. Hotovo.
2, Tad si zvolil dobre. Ak ti momentalne nezalezi na extra rychlom prevode, tak takto je to dobre zvolene, aj s tymi RC hodinami. Urobil by som to tiez tak.
3, Right alebo left justified result - no podla toho, co potrebujes. Ak das RJR, tak budes mat spodny byte 10-bitoveho vysledku v ADRESL a horne dva bity v dolnych dvoch bitoch ADRESH. To je dobre ked potrebujes cely 10-bitovy vysledok, potom to do int premennej das asi takto:

unsigned int result;
result = (((unsigned int) (ADRESH))<<8) + ADRESL;

AK si zvolis LJR, tak to je zas lepsie ak nepotrebujes celych 10 bitov, ale staci ti len 8 bitov, tak rovno v ADRESH mas hornych 8 bitov prevodu (v hornych dvoch bitoch ADRESL mas dolne dva bity vysledku) a potom to mozes urobit takto:

unsigned char result;
result = ADRESH;

4, kompialtor - no ked ti staci MikroC, tak OK, nenutim ta :slight_smile: Pracuj s tym, co ti vyhovuje, ale mne, ako aj inym ludom, co sa programovanim zivia, viac vyhovuje to co som spominal, okrem toho su tam aj vyhody “nematerialneho” (kompialtor je sam nematerialny, ale ved chapeme) charakteru, napriklad lepsia podpora vyrobcu, vacsia uzivatelska zakladna atd.

Inak nikdy nepouzivam HW kniznice od kompilatora, takze take nieco ako ADC_Read(1) ani nie.
Nejak mi nerobi problem sam si napisat taketo elementarne funkcie pre pristup k HW - tak ako tak ro byva na par riadkov, ale su to klucove funkcie a je dobre ich mat na 100% pod kontrolou - a mnohokrat to clovek potrebuje mat inak ako to je v knizniciach.[/code]

Ok ok díky…
takže kod upraven(snad už to bude i měřit - odzkouším až budu mít PicKit2 a MCU)

Raději jsem tedy zvolil RJR protože ještě přesně nevim jako moc to bude zapotřebí mít přesné(i když předpokládám že i 8 bitů bude stačit). Kompilítor se sice tváří že jako “ok” ale … :smiley:

Jen si nejsem jist zápisem:

while(ADCON0!=0b00000001);
Sice to funguje tak jak má(co si teda alespoň myslim) ale určitě by to šlo zapsat i nějak elegantněji(resp. testovat jen ten daný bit).

Celý zdroják

unsigned int napeti,temp;

void main() {
  TRISA  = 0xFF;              // PORTA je vstup
  TRISB  = 0x00;                 // PORTB je vystup
  ADCON0 = 0b00000001;
  ADCON1 = 0b01111110;
  ADCON2 = 0b10110111;


  do {
    ADCON0 = 0b00000011;
    while(ADCON0!=0b00000001);
    temp = (((unsigned int) (ADRESH))<<8) + ADRESL;

    if (temp>=1 && temp<3){
        PORTB = 1; //Stav 1
    }

    if (temp>=3 && temp<6){
        PORTB = 2; //Stav 2
    }

    if (temp>=6 && temp<9){
        PORTB = 4; //Stav 3
    }

    if (temp>=9 && temp<12){
        PORTB = 8; //Stav 4
    }

    if (temp>=12 && temp<15){
        PORTB = 16; //Stav 5
    }
  } while(1);
}

“while(ADCON0!=0b00000001);”
Tak to není dobrej nápad. Pokud bude z nějakáho důvodu nastaven i jiný bit, než na který čekáš (předpokládám, že čekáš na vynulování bitu 1), tak program do dalšího resetu končí.
Lepší řešení je while(ADCON0 & 0b00000010); // čekej dokud je bit 1 nastaven a ostatních si nevšímej
Navíc se ten bit určitě nějak jmenuje, takže nejpřehlednější by bylo:
while(ADCON0 & (1<<jmenoBitu));

Díky díky… vim o tom, že by můj zápis mohl dělat problémy ale bohužel bitové operace jsem se ještě pořádně nenaučil . Teď už jsem zase o něco chytřejší :slight_smile: .
Název bitu je “GO/DONE” s tím, že u DONE je negace(čára nad ním).

Zkus to čtení z AD třeba nějak takto:

Zadat ADCON. mě nenapadlo :smiley:.
Po zadání ADCON0. vyjel seznam a tam jsem si již mohl vybrat to co jsem potřeboval(.GO resp: .GO_DONE)
Takže nakonec upraveno na:

while(ADCON0.GO_DONE);

Instrukce kterou jsi popsal pouze čeká na ukončení AD převodu, přední musí být ještě ta, co AD převod zapne.

jj vim… předtím jsem samozřejmě nechal(i když tedy “ne tak hezký” zápis)

ADCON0 = 0b00000011;

Jinak PICKIT2 už je doma, tak teď ještě musim vyrazit na nákupy :smiley: a už to budu moct konečně odzkoušet v reálu :d

No, to nevím jak bude fungovat: