Vai al contenuto
PLC Forum


PIC 12F1572


dott.cicala

Messaggi consigliati

io non ho scritto che tu dicevi che arduino fosse un bidone...dove lo vedi ....io ho scritto "passa ad arduino che fai prima 2...non e' la stessa cosa ti pare?

 

Link al commento
Condividi su altri siti


  • Risposte 66
  • Created
  • Ultima risposta

Top Posters In This Topic

  • dott.cicala

    38

  • Livio Orsini

    12

  • walterword

    8

  • gabri-z

    5

io non ho scritto

sono un po' paranoico e soffro di manie di persecuzione .....e l'ho letto tra le righe nel messaggio precedente.:wacko:

Li sto avendo or ora i dispiaceri con MPLAB X :superlol: Prima di tutto perché il corso appena scaricato e stampato (a colori!!) ...è PIC32 based oltre ad essere orientato a piazzare...la loro demoboard.....

Il 12F1572, pur essendo un 8pin, fa parte dei mid range, è sul mercato dal 2013 e c'è pochissimo in rete...e quel poco che c'è è incompleto.

Questo invece è un esempio - sia pur migliorabile - funzionante.

Basta scaricare MikroC, che non avrà niente di professionale ma per scopi dilettantistici è più che sufficiente, copiare-incollare il codice qui sopra, avendo cura di settare i fuses come da immagine, programmare il pic con il pickit3, realizzare il circuito su mille fori....e si ha già qualcosa di funzionante...senza impazzire con l'assembly.

E in un colpo solo, viene usato un ingresso analogico, i tre pwm e un piccolo esempio su come traslare da un paio di pins ad altri due le funzioni pwm, agendo sul registo

APFCON  = 0b00000011;    // Alternate Pin Function: PW1->RA5 - PWM2->RA4

Si ha che RA0, RA1 che di default fanno capo a PWM2 - PWM1, vengono usati come ingressi

TRISA   = 0b11001011;    // RA2-RA4-RA5=OUT - RA0-RA1-RA3=INPUT

i quali sono configurati come Schmitt Triggered insieme ad RA3 che a sua volta è configurato come ingresso e non come MCLR

INLVLA  = 0b00001011;    // Ctrl.Ingressi 0=TTL-1=Schmitt Triggered

 RA0 è usato come ingresso analogico

ANSELA  = 0b00000001;    // Ingressi Anaogici RA0=AN0

I PWM non sono triggerati dai loro bit LDA, cioè il bit 7 dei rispettivi registri PWMxLDCON

       sbit Load1   at PWM1LDCON.B7;
       sbit Load2   at PWM2LDCON.B7;
       sbit Load3   at PWM3LDCON.B7;

ma vengono triggerati simultaneamente per mezzo del registro mirror PWMLD scrivendo 111 nei bit da 0 a 2

PWMLD=0x7;

II bit del registo mirror PWMLD o dei rispettivi registri PWMxLDCON vedranno resettati dall'hardware non appena il nuovo valore viene assunto dai moduli PWM evitando così fenomeni di glitch.

 

 

 

Peccato che il DAC interno abbia solo 5 bit....ma l'idea di farci un DDS a bassa frequenza mi solletica molto. Un generatore di onde quadre a duty cycle programabile....è già nell'esempio qui sopra...con un po' di fantasia....e pure a 3 canali indipendenti....e volendo...si può sincronizzarli, modificare fase , offset, perido....senza dover passare per MPLAB X

Modificato: da dott.cicala
Link al commento
Condividi su altri siti

Peccato che il DAC interno abbia solo 5 bit....ma l'idea di farci un DDS a bassa frequenza mi solletica molto.

Dai sintetizzare una sinusoide su solo 31 livelli discreti è.......come usare un vecchio inverter 3 steps.:lol:

Livio non perdere tempo a studiare i ragnetti .....cerca il circuito DDS

Se vuoi farti un DDS con Arduino non c'è problema ne possiamo parlare, anche se non vedo l'utilità.

Link al commento
Condividi su altri siti

Un DDS fatto direttamente con Arduino....avrà prestazioni limitate ....meglio comandare con Arduino in seriale o parallelo un AD9851 o un AD9858,

allora sì che si può fare un DDS decente......c'è già tutto pronto....basta attaccare i fili :lol:

 

Link al commento
Condividi su altri siti

Tornando al PIC12F1572.....e lasciando per un attimo i PWM,  un'altra periferica semplice ma interessante è.....

7ce14d37365db7dc06d7803cebcc753a.JPG

ll range parte da -40°C per arrivare a +85°C.

urge preparare uno schemino per metterla alla prova

Modificato: da dott.cicala
Link al commento
Condividi su altri siti

Pilotare gli stepper direttamente da Arduino, va bene se si realizzano giochini. Se vuoi fare un qualche cosa per alte prestazioni, con microstepping e rampe di accelerazione e decelerazione, allora è da rivedere un po' tutto.

Link al commento
Condividi su altri siti

io ho due stepper nema 23 e due drive TBxxx 

Sto cercando di creare un semplice motion control con Arduino. Il treno di impulsi esce dal motion ossia da Arduino.Per fare questo sto facendo dei test usando l'interrupt di un timer .Rammpe , accelerazioni, selezione velocità, calcolo delle traiettorie etc le implemento nel software , che gira su Aduino.

E' un po più chiaro quello che vorrei fare ? ......

Link al commento
Condividi su altri siti

....E meno male che avevo definito semplice il Temperature Sensor Indicator ! :wacko:

MikroC...ovviamente non è capace di gestirlo e quindi, se si hanno più ingressi analogici come ho voluto fare io....non si può più utilizzare la comoda funzione di libreria  ADC_Read().

La comodità di questa funzione consiste nel fatto che, una volta definiti gli ingressi con il registro TRIS e definiti gli analogici con il registro ANSEL,

è sufficiente richiamarla per leggere direttamente il canale analogico, così, ad esempio per leggere RA0 configurato ingresso analogico, basta scrivere

Var1=ADC_Read(0)  per leggere AN0

Var1=ADC_Read(1)  per leggere AN1

ecc.

Per leggere invece il sensore di temperatura....non è possibile usare la funzione, nemmeno per leggere altri canali analogici...perchè.....il convertitore AD è uno solo e viene multiplexato....e la funzione di libreria si occupa anche di questa gestione.

E' quindi necessario capire come funziona il convertitoreAD a 10 bit....e tutti i suoi registri :(...lasciando perdere per un momento quelli dedicati agli Interrupts

0305642c17c3b0be8938f08f41cc2703.JPG

...lo schema logico del convertitore non lascia spazio a dubbi :superlol:...per utilizzare il sensore di temperatura è necessario agire anche sul registro 

FVRCON cioè il registo che controlla il Fixed Voltage Reference, ed agire almeno sul bit di abilitazione del sensore di temperatura, che si chiama

TSEN   e quindi FVRCON.TSEN=1;  e il sensore è abilitato. E' inoltre necessario scegliere il range, agendo su TSRNG sempre di FVRCON.

FVRCON.TSRNG=1  cortocircuita 2 diodi e si ha il range basso, che va bene con una tensione di alimentazione bassa (1.8 a 3,6V)

FVRCON.TSRNG=0 vengono usati tutti e 4 i diodi...e va bene con tensioni di alimentazioni >=3,6V

Ora, siccome nel mio prototipo ho usato anche altri due ingressi analogici.....il codice diventa così:

//******************************************************************************
// Project :            Standard Mode PWM Test
// Author  :            S.T. 4 Plc Forum
//                      Ingressi Analogici - Temp.Sens. Indicator
// Date    :            22/12/2015
// MCU     :            PIC12F1572 - INT.OSC. 32MHz
// Compiler:            MikroC PRO for PIC V6.6.2
//******************************************************************************
//****** TAGs ******************************************************************
       sbit Load1   at PWM1LDCON.B7;
       sbit Load2   at PWM2LDCON.B7;
       sbit Load3   at PWM3LDCON.B7;
       sbit man     at RA3_BIT;
       float act_temp;
       unsigned int Dc1, Dc2, Dc3, DutyCycle;
       unsigned int AnVal1, AnVal2, AnVal3, CalVal;
       char Catt[8];
       bit dn, up, start;
//******************************************************************************
//******************************************************************************
void main() {
//******************************************************************************
// Registro configurazione Oscillatore
//******************************************************************************
       OSCCON  = 0b11110000;    // Int Osc 32MHz 4xPLL ON
       OSCTUNE = 0b00111111;    // Max Frequency
//******************************************************************************
// Registri configurazione PORT[A]
//******************************************************************************
       WPUA    = 0b00000000;    // Resistenze Pull Up disattivate
       SLRCONA = 0b00000000;    // Slew Rate non limitato
       INLVLA  = 0b00001011;    // Ctrl.Ingressi 0=TTL-1=Scmitt Triggered
       ODCONA  = 0b00000000;    // Ctrl. Outputs 0=Totem Pole-1=Open Drain
       APFCON  = 0b00000011;    // Alternate Pin Function: PW1->RA5 - PWM2->RA4
       TRISA   = 0b11001011;    // RA2-RA4-RA5=OUT - RA0-RA1-RA3=INPUT
       LATA    = 0b00000000;    // PORT[A] Latch register
       ANSELA  = 0b00000011;    // Ingressi Anaogici RA4=AN3
//******************************************************************************
// Registri configurazione INTERRUPTS
//******************************************************************************
       INTCON  = 0b00000000;    // INTERRUPTS CTRL REGISTER
       PIE1    = 0b00000000;    // PERIPHERAL INTERRUPT ENABLE REGISTER 1
       PIE2    = 0b00000000;    // PERIPHERAL INTERRUPT ENABLE REGISTER 2
       PIE3    = 0b00000000;    // PERIPHERAL INTERRUPT ENABLE REGISTER 3
       PIR1    = 0b00000000;    // PERIPHERAL INTERRUPT REQUEST REGISTER 1
       PIR2    = 0b00000000;    // PERIPHERAL INTERRUPT REQUEST REGISTER 2
       PIR3    = 0b00000000;    // PERIPHERAL INTERRUPT REQUEST REGISTER 3
       IOCAP   = 0b00000000;    // INTERRUPT-ON-CHANGE PORT[A] POS.EDGE REGISTER
       IOCAN   = 0b00000000;    // INTERRUPT-ON-CHANGE PORT[A] NEG.EDGE REGISTER
       IOCAF   = 0b00000000;    // INTERRUPT-ON-CHANGE PORT[A] FLAG REGISTER
//******************************************************************************
// Registri configurazione 16-BIT PWM MODULE
//******************************************************************************
//----RA1 - PWM1 ---------------------------------------------------------------
       PWM1CON   = 0b11000000;    // module en, output en, norm pol, standard m.
       PWM1CLKCON= 0b00100001;    // HFINTOSC clock, Prescaler /4
       PWM1PR    = 0x3FF;         // PWM PERIOD COUNT REGISTER
       PWM1PH    = 0x3FF;         // PWM PHASE  COUNT REGISTER
//----RA0 - PWM2 ---------------------------------------------------------------
       PWM2CON   = 0b11000000;    // module en, output en, norm pol, standard m.
       PWM2CLKCON= 0b00100001;    // HFINTOSC clock, Prescaler /4
       PWM2PR    = 0x3FF;         // PWM PERIOD COUNT REGISTER
       PWM2PH    = 0x3FF;         // PWM PHASE  COUNT REGISTER
//----RA2 - PWM3 ---------------------------------------------------------------
       PWM3CON   = 0b11000000;    // module en, output en, norm pol, standard m.
       PWM3CLKCON= 0b00100001;    // HFINTOSC clock, no prescaler
       PWM3PR    = 0x3FF;         // PWM PERIOD COUNT REGISTER
       PWM3PH    = 0x3FF;         // PWM PHASE  COUNT REGISTER
//----PWM MIRROR REGISTERS -----------------------------------------------------
       PWMLD     = 0x000;         // PWM LOAD SIMULTANEOUSLY REGISTER
//******************************************************************************
// REGISRTI AD
//******************************************************************************
       ADCON1    = 0b10010000;    // Right Justfied - AD Clk = Fosc/32 = 1uS
       ADCON2    = 0b00000000;    // No Autoconversion Trigger
//******************************************************************************
// Temperature Indicator Module - Valore di Calibrazione
//******************************************************************************
       CalVal=517;
//******************************************************************************
// Lettura AN0 - RA0
//******************************************************************************
   while(1)
     {
         ADCON0.CHS0 =0;          // BIT0 - AN SELECTOR |
         ADCON0.CHS1 =0;          // BIT1 - AN SELECTOR |
         ADCON0.CHS2 =0;          // BIT2 - AN SELECTOR |- RA0 SELEZIONATO
         ADCON0.CHS3 =0;          // BIT3 - AN SELECTOR |
         ADCON0.CHS4 =0;          // BIT4 - AN SELECTOR |
         ADCON0.ADON =1;          // ATTIVO CONVERTITORE AD
         delay_us(5);             // ATTENDO 5us
         ADCON0.GO   =1;          // ATTIVO LA CONVERSIONE
         delay_us(11);            // ATTENDO 11us
         AnVal1=ADRES;            // TRASFERISCO VALORE AD SU VARIABILE1
         ADCON0.GO   =0;          // DISATTIVO LA CONVERSIONE
         ADCON0.ADON =0;          // DISATTIVO CONVERTITORE AD
//******************************************************************************
// Lettura AN1 - RA1
//******************************************************************************
         ADCON0.CHS0 =1;          // BIT0 - AN SELECTOR |
         ADCON0.CHS1 =0;          // BIT1 - AN SELECTOR |
         ADCON0.CHS2 =0;          // BIT2 - AN SELECTOR |- RA1 SELEZIONATO
         ADCON0.CHS3 =0;          // BIT3 - AN SELECTOR |
         ADCON0.CHS4 =0;          // BIT4 - AN SELECTOR |
         ADCON0.ADON =1;          // ATTIVO CONVERTITORE AD
         delay_us(5);             // ATTENDO 5us
         ADCON0.GO   =1;          // ATTIVO LA CONVERSIONE
         delay_us(11);            // ATTENDO 11us
         AnVal2=ADRES;            // TRASFERISCO VALORE AD SU VARIABILE2
         ADCON0.GO   =0;          // DISATTIVO LA CONVERSIONE
         ADCON0.ADON =0;          // DISATTIVO CONVERTITORE AD
//******************************************************************************
// Lettura Temperature Indicator Module
//******************************************************************************
         FVRCON.TSRNG=0;          // RANGE SENSORE TEMPERATURA
         FVRCON.TSEN =1;          // ABILITAZIONE SENSORE TEMPERATURA
         ADCON0.CHS0 =1;          // BIT0 - AN SELECTOR |
         ADCON0.CHS1 =0;          // BIT1 - AN SELECTOR |
         ADCON0.CHS2 =1;          // BIT2 - AN SELECTOR |- TEMP.Sens.Indicator
         ADCON0.CHS3 =1;          // BIT3 - AN SELECTOR |
         ADCON0.CHS4 =1;          // BIT4 - AN SELECTOR |
         ADCON0.ADON =1;          // ATTIVO CONVERTITORE AD
         delay_us(5);             // ATTENDO 5us
         ADCON0.GO   =1;          // ATTIVO LA CONVERSIONE
         delay_us(11);            // ATTENDO 11us
         AnVal3=ADRES;            // TRASFERISCO VALORE AD SU VARIABILE2
         ADCON0.GO   =0;          // DISATTIVO LA CONVERSIONE
         ADCON0.ADON =0;          // DISATTIVO CONVERTITORE AD
         FVRCON.TSEN =0;          // DISATTIVO SENSORE TEMPERATURA
//******************************************************************************
// Temperatura attuale [°C]
//******************************************************************************
         act_temp=((0.659-(1.25)*(1.0-((AnVal3-CalVal)/1022.0)))/0.00132))-40.0;

         FloatToStr(act_temp,Catt);
  // Temperatura da trasferire via UART
//******************************************************************************
// Comando PWM1-PWM2-PWM3
//******************************************************************************
         Dc1=AnVal1;
         Dc2=AnVal2;
         Dc3=AnVal3;
         PWMLD=0x7;
         
         PWM1DC = Dc1; //RA5
         PWM2DC = Dc2; //RA4
         PWM3DC = Dc3; //RA2
     }
 }

 

 

 

Modificato: da dott.cicala
Link al commento
Condividi su altri siti

...in pratica, per leggere i canali analogici abilitati è necessario rispettare questo diagramma temporale...

662ba5c35a27a899429ea0c18aa263d8.JPG

TAD è funzone del clock e del fattore di divisione. In questo caso il clock è 32MHz e il fattore di divisione è 32 --> TAD=1us

Dall'abilitazione del convertitore 

ADCON0.ADON =1

è necessario attendere almeno 4*TAD prima di attivare la conversione

ADCON0.GO   =1;

A questo punto, trascorso il tempo cha va da TACQ a TAD11, in questo caso forzato a 16us, in AnVal3 è contenuto il valore di conversione "Right justified"

ADCON1    = 0b10010000;    // Right Justfied - AD Clk = Fosc/32 = 1uS

relativo al temperature sensor indictator. (In realtà ADCON0.GO viene resettato dall'AD a conversione avvenuta...)

AnVal3=ADRES;            // TRASFERISCO VALORE AD SU VARIABILE3

 

 

 

Affinché si abbia una lettura precisa, è necessario effettuare una calibrazione ad almeno un punto e ricavare il valore di calibrazione "CalVal" 

Quindi, il calcolo della temperatura attuale in float, e la conversione in string[8] per poter essere trasmessa via UART ad un display...eventuale.

//******************************************************************************
// Temperatura attuale [°C]
//******************************************************************************
         act_temp=((0.659-(1.25)*(1.0-((AnVal3-CalVal)/1022.0)))/0.00132))-40.0;

         FloatToStr(act_temp,Catt);        // Temperatura da trasferire via UART

Per la calibrazione, fare riferimento alla AN1333 dove si trova anche questa

936603283eb8ad3df620d25d7a5fa038.JPG

 

Si potrebbe riscalare il valore di conversione in modo tale che per un range di temperatura il pwm3 abbia un duty cycle da 0 a 100%

per comandare una ventola....e abbiano ancora un ingresso libero che si potrebbe usare per il controllo di rotazione o come feedback di velocità....

 

 

 

Non male per un coso grande quanto un 555 vero? :smile:

Modificato: da dott.cicala
Link al commento
Condividi su altri siti

A questo punto molto più semplice e comodo usare un DS1820 in I2C, che è anche più preciso:lol:

Battute a parte io credo che questo dispositivo sia stato progettato per poter risolvere molti differenti problemi, però uno alla volta. 

Certo che per un 8 pins le prestazioni sono veramente eccezionali.

Walter saimo completamente OT e rischiamo di fare una grande confusione con  la storia degli stepper. Apri, se vuoi un'altra discussione.

Link al commento
Condividi su altri siti

Effettivamente il sensore di temperatura non ha una grande precisione.  Ma per gli copi per i quali è stato progettato, la sua precisione è sufficiente.

 

Immaginiamo che invece di un DIL8 stiamo usando un 12F1572 in case MSOP, quindi smd, e sullo stesso pcb ci siano dei mos power...e che il pcb sia montato a ridosso della loro aletta di raffreddamento...Il sensore di temperatura potrebbe controllare una ventola e mandare in protezione il sistema in caso di temperatura eccessiva...e per fare ciò, non è necessario calcolare la temperatura in °C.

Oltretutto, la funzione che ho usato per la conversione...è eccessiva,  sia perché calcolata in float (virgola mobile 32bit), sia perchè viene usata una funzione di libreria per convertire da float a string.

 

 act_temp=((0.659-(1.25)*(1.0-((AnVal3-CalVal)/1022.0)))/0.00132))-40.0;  //Floating point 32bit

         FloatToStr(act_temp,Catt);                                       // Temperatura da trasferire via UART

Memoria occupata senza la funzione di cui sopra

fa3ad1d3ef702b00e9eac1a0283c532f.JPG

Memoria occupata con  funzione e conversione Float to String

bab54d53561caf34715ca1dd25d6abad.JPG

Urge fare i conti diversamente, abbandonando la comodità della virgola mobile per passare alla notazione Unsigned Int che impegna 16bit è può rappresentare un valore max di 65535.....

Oltre all'inutile spreco di memoria, c'è da considerare quanti cicli di clock sarebbero necessari per svolgere il calcolo.

Volendo,si può anche calcolare...sapendo che il clock è a 32MHz.....

Modificato: da dott.cicala
Link al commento
Condividi su altri siti

No...però volendo si può migliorare e risparmiare. Nel frattempo ho fatto alcune misure raffreddando e scaldando il chip e misurando la temperatura con un termometro IR. Ne è venuto fuori questo grafico.

a3e5c96b8647724aa1e3a31b42c0b43c.JPG

La curva arancio (counts vs °C) è prodotta dalla formula microchip senza aggiungere il valore di calibrazione. 

la curva blu è stata ottenuta ricavando i valori min e max count raffreddando e riscaldando e, considerando che la funzione temperatura corrente nei diodi è lineare, ho riscalato in uint per pilotare il pwm

//******************************************************************************
// Temperatura attuale
//******************************************************************************
//       In_min =743;       Out_min =102;
//       In_max =797;       Out_max =1022;
         
         act_temp=((AnVal3-In_min)/(In_max-In_min)*(Out_max-Out_min))+Out_min;
//******************************************************************************
// Comando PWM1-PWM2-PWM3
//******************************************************************************
         Dc1=AnVal1;
         Dc2=AnVal2;
         Dc3=act_temp;
         PWMLD=0x7;
         
         PWM1DC = Dc1; //RA5
         PWM2DC = Dc2; //RA4
         PWM3DC = Dc3; //RA2

Ora si può comandare una ventola in funzione della temperatura del chip.....e l'occupazione di memoria diventa così

24c59a213ec5c3090450acff31caef70.jpg

Rimane spazio per fare qualcos'altro: Il controllo rotazione tramite l'ingresso RA3 rimasto libero.

Link al commento
Condividi su altri siti

Lo scaling con interi non va bene.

(AnVal3-In_min)/(In_max-In_min)

Il risultato di questa in intero può assumere solo due valori:

 - Zero per il valore minimo di ingresso

- UNO per il valore massimo di ingresso

 

Di conseguenza il risultato  della

act_temp=((AnVal3-In_min)/(In_max-In_min))*(Out_max-Out_min)+Out_min;

ha solo due valori:

- Out_min

- Out_max

La soluzione più semplice è usare il float e convertire il risultato in INT

act_temp=(int)(Out_min+(((In_Val -In_min)/(In_max-In_min))*(Out_max-Out_min)));

Rimane comunque abbastanza memoria per fare qualcos'altro

cc41d745116dd85795a1b51d5a956911.jpg

Da tutto ciò è evidente che il Temperature Indicator Module è più adatto ad una regolazione ON-OFF piuttosto che lineare...

Modificato: da dott.cicala
Link al commento
Condividi su altri siti

Grazie!

Nel frattempo :smile:....dopo una nottata a raffreddare e riscaldare il PIC con mezzi ultra professionali :lol:(lattina gelata e stazione dissaldante con getto a 100°C)

sono riuscito a calibrare meglio la scala e quindi...mi devo ricredere. Una volta calibrata la scala, è possibile eseguire una regolazione lineare dell'uscita PWM che comanda la ventola.

Ecco il risultato finale

//******************************************************************************
// Project :            Standard Mode PWM Test
// Author  :            S.T. 4 Plc Forum
//                      Ingressi Analogici - Temp.Sens. Indicator
// Date    :            22/12/2015
// MCU     :            PIC12F1572 - INT.OSC. 32MHz
// Compiler:            MikroC PRO for PIC V6.6.2
//******************************************************************************
//****** TAGs ******************************************************************
       sbit Load1   at PWM1LDCON.B7;
       sbit Load2   at PWM2LDCON.B7;
       sbit Load3   at PWM3LDCON.B7;
       sbit trip    at RA3_BIT;
       unsigned int Dc1, Dc2, Dc3;
       unsigned int AnVal1, AnVal2, AnVal3, Temp;
       float In_min, In_max, Out_min, Out_max;
       bit mem;
//******************************************************************************
//******************************************************************************
void main() {
//******************************************************************************
// Registro configurazione Oscillatore
//******************************************************************************
       OSCCON  = 0b11110000;    // Int Osc 32MHz 4xPLL ON
       OSCTUNE = 0b00111111;    // Max Frequency
//******************************************************************************
// Registri configurazione PORT[A]
//******************************************************************************
       WPUA    = 0b00000000;    // Resistenze Pull Up disattivate
       SLRCONA = 0b00000000;    // Slew Rate non limitato
       INLVLA  = 0b00001011;    // Ctrl.Ingressi 0=TTL-1=Scmitt Triggered
       ODCONA  = 0b00000000;    // Ctrl. Outputs 0=Totem Pole-1=Open Drain
       APFCON  = 0b00000011;    // Alternate Pin Function: PW1->RA5 - PWM2->RA4
       TRISA   = 0b11001011;    // RA2-RA4-RA5=OUT - RA0-RA1-RA3=INPUT
       LATA    = 0b00000000;    // PORT[A] Latch register
       ANSELA  = 0b00000011;    // Ingressi Anaogici RA4=AN3
//******************************************************************************
// Registri configurazione INTERRUPTS
//******************************************************************************
       INTCON  = 0b00000000;    // INTERRUPTS CTRL REGISTER
       PIE1    = 0b00000000;    // PERIPHERAL INTERRUPT ENABLE REGISTER 1
       PIE2    = 0b00000000;    // PERIPHERAL INTERRUPT ENABLE REGISTER 2
       PIE3    = 0b00000000;    // PERIPHERAL INTERRUPT ENABLE REGISTER 3
       PIR1    = 0b00000000;    // PERIPHERAL INTERRUPT REQUEST REGISTER 1
       PIR2    = 0b00000000;    // PERIPHERAL INTERRUPT REQUEST REGISTER 2
       PIR3    = 0b00000000;    // PERIPHERAL INTERRUPT REQUEST REGISTER 3
       IOCAP   = 0b00000000;    // INTERRUPT-ON-CHANGE PORT[A] POS.EDGE REGISTER
       IOCAN   = 0b00000000;    // INTERRUPT-ON-CHANGE PORT[A] NEG.EDGE REGISTER
       IOCAF   = 0b00000000;    // INTERRUPT-ON-CHANGE PORT[A] FLAG REGISTER
//******************************************************************************
// Registri configurazione 16-BIT PWM MODULE
//******************************************************************************
//----RA5 - PWM1 ---------------------------------------------------------------
       PWM1CON   = 0b11000000;    // module en, output en, norm pol, standard m.
       PWM1CLKCON= 0b00100001;    // HFINTOSC clock, Prescaler /4
       PWM1PR    = 0x3FF;         // PWM PERIOD COUNT REGISTER
       PWM1PH    = 0x3FF;         // PWM PHASE  COUNT REGISTER
//----RA4 - PWM2 ---------------------------------------------------------------
       PWM2CON   = 0b11000000;    // module en, output en, norm pol, standard m.
       PWM2CLKCON= 0b00100001;    // HFINTOSC clock, Prescaler /4
       PWM2PR    = 0x3FF;         // PWM PERIOD COUNT REGISTER
       PWM2PH    = 0x3FF;         // PWM PHASE  COUNT REGISTER
//----RA2 - PWM3 ---------------------------------------------------------------
       PWM3CON   = 0b11000000;    // module en, output en, norm pol, standard m.
       PWM3CLKCON= 0b00100001;    // HFINTOSC clock, no prescaler
       PWM3PR    = 0x3FF;         // PWM PERIOD COUNT REGISTER
       PWM3PH    = 0x3FF;         // PWM PHASE  COUNT REGISTER
//----PWM MIRROR REGISTERS -----------------------------------------------------
       PWMLD     = 0x000;         // PWM LOAD SIMULTANEOUSLY REGISTER
//******************************************************************************
// REGISRTI AD
//******************************************************************************
       ADCON1    = 0b10010000;    // Right Justfied - AD Clk = Fosc/32 = 1uS
       ADCON2    = 0b00000000;    // No Autoconversion Trigger
//******************************************************************************
// Temperature Indicator Module - Valori Scaling
//******************************************************************************
       In_min =747.5;            Out_min =0.;
       In_max =815.;             Out_max =1022.;
       mem    =0;
//******************************************************************************
// Lettura AN0 - RA0
//******************************************************************************
      while(1)
        {
         ADCON0.CHS0 =0;          // BIT0 - AN SELECTOR |
         ADCON0.CHS1 =0;          // BIT1 - AN SELECTOR |
         ADCON0.CHS2 =0;          // BIT2 - AN SELECTOR |- RA0 SELEZIONATO
         ADCON0.CHS3 =0;          // BIT3 - AN SELECTOR |
         ADCON0.CHS4 =0;          // BIT4 - AN SELECTOR |
         ADCON0.ADON =1;          // ATTIVO CONVERTITORE AD
         delay_us(6);             // ATTENDO 6us
         ADCON0.GO   =1;          // ATTIVO LA CONVERSIONE
         delay_us(11);            // ATTENDO 11us
         AnVal1=ADRES;            // TRASFERISCO VALORE AD SU VARIABILE1
         ADCON0.GO   =0;          // DISATTIVO LA CONVERSIONE
         ADCON0.ADON =0;          // DISATTIVO CONVERTITORE AD
//******************************************************************************
// Lettura AN1 - RA1
//******************************************************************************
         ADCON0.CHS0 =1;          // BIT0 - AN SELECTOR |
         ADCON0.CHS1 =0;          // BIT1 - AN SELECTOR |
         ADCON0.CHS2 =0;          // BIT2 - AN SELECTOR |- RA1 SELEZIONATO
         ADCON0.CHS3 =0;          // BIT3 - AN SELECTOR |
         ADCON0.CHS4 =0;          // BIT4 - AN SELECTOR |
         ADCON0.ADON =1;          // ATTIVO CONVERTITORE AD
         delay_us(6);             // ATTENDO 6us
         ADCON0.GO   =1;          // ATTIVO LA CONVERSIONE
         delay_us(11);            // ATTENDO 11us
         AnVal2=ADRES;            // TRASFERISCO VALORE AD SU VARIABILE1
         ADCON0.GO   =0;          // DISATTIVO LA CONVERSIONE
         ADCON0.ADON =0;          // DISATTIVO CONVERTITORE AD
//******************************************************************************
// Lettura Temperature Indicator Module
//******************************************************************************
         FVRCON.TSRNG=0;          // RANGE SENSORE TEMPERATURA
         FVRCON.TSEN =1;          // ABILITAZIONE SENSORE TEMPERATURA
         ADCON0.CHS0 =1;          // BIT0 - AN SELECTOR |
         ADCON0.CHS1 =0;          // BIT1 - AN SELECTOR |
         ADCON0.CHS2 =1;          // BIT2 - AN SELECTOR |- TIM SELEZIONATO
         ADCON0.CHS3 =1;          // BIT3 - AN SELECTOR |
         ADCON0.CHS4 =1;          // BIT4 - AN SELECTOR |
         ADCON0.ADON =1;          // ATTIVO CONVERTITORE AD
         delay_us(250);           // ATTENDO 250us
         ADCON0.GO   =1;          // ATTIVO LA CONVERSIONE
         delay_us(202);           // ATTENDO 202us
         AnVal3=ADRES;            // TRASFERISCO VALORE AD SU VARIABILE2
         ADCON0.GO   =0;          // DISATTIVO LA CONVERSIONE
         ADCON0.ADON =0;          // DISATTIVO CONVERTITORE AD
         FVRCON.TSEN =0;          // DISATTIVO SENSORE TEMPERATURA
//******************************************************************************
// Scaling Temperature Indicator Module vs PWM - CTRL limiti
//******************************************************************************
         if(AnVal3<In_min)AnVal3=In_min;
         if(AnVal3>In_max)AnVal3=In_max;
//******************************************************************************
// Scaling Temperature Indicator Module vs PWM
//******************************************************************************
  Temp=(int)(Out_min+(((AnVal3-In_min)/(In_max-In_min))*(Out_max-Out_min)));
//******************************************************************************
// Trip
//******************************************************************************
        if(trip)
         {
          AnVal1=0;
          AnVal2=0;
          Temp  =0;
         }
//******************************************************************************
// Comando PWM1-PWM2-PWM3
//******************************************************************************
         Dc1=AnVal1;   // RA0 AI --> RA5 OUT PWM[2]
         Dc2=AnVal2;   // RA1 AI --> RA4 OUT PWM[1]
         Dc3=Temp;     // Temperature Indicator Module
         PWMLD=0x7;    // PWM1-2-3 LOAD TRIGGER SOURCE
         
         PWM1DC = Dc1; //RA5 OUT PWM[2]
         PWM2DC = Dc2; //RA4 OUT PWM[1]
         PWM3DC = Dc3; //RA2 OUT PWM[TIM]
     }
 }

E' stato necessario aggiungere il controllo dei limiti

//******************************************************************************
// Scaling Temperature Indicator Module vs PWM - CTRL limiti
//******************************************************************************
         if(AnVal3<In_min)AnVal3=In_min;
         if(AnVal3>In_max)AnVal3=In_max;

BUON NATALE!

Modificato: da dott.cicala
Link al commento
Condividi su altri siti

Dopo la pausa natalizia....un altro progettino interessante: PSTN-DTMF converter...senza quarzo e senza integrati speciali.

Il solo 12F1572 riesce a far tutto. Alimentato dalla linea telefonica, il circuito è abbastanza piccolo da trovar posto all'interno di un vecchio telefono dei nonni a composizione decadica che desideravo riportare in servizio

c46655992eff8c74182a5e9d4fdb9fb9.jpg 

//******************************************************************************
// Project :            PSTN-DTMF Converter - senza quarzo
// Author  :            S.T. 4 my old phone
// Date    :            29/12/2015
// MCU     :            PIC12F1572 - INT.OSC. 8MHz
// Compiler:            MikroC PRO for PIC V6.6.2
//******************************************************************************
//****** TAGs ******************************************************************
       sbit Pulses  at RA3_BIT;
       sbit Led     at RA5_BIT;
       unsigned int Dc1, Dc2, Dc3;
       int num;
       bit mem1; mem2;
//******************************************************************************
// FREQUENZE DTMF
//******************************************************************************
/*        +--- +-------------------+          +-------------------------+
          | Hz |1209|1336|1477|1633|          | PITCH | f. richieste Hz |
     +----+----+----+----+----+----+          +-------------------------+
     | Y1 |697 | 1  | 2  | 3  | A  |          | 716   |     697         |
     +----+----+----+----+----+----+          +-------------------------+
     | Y2 |770 | 4  | 5  | 6  | B  |          | 650   |     770         |
     +----+----+----+----+----+----+          +-------------------------+
     | Y3 |852 | 7  | 8  | 9  | C  |          | 587   |     852         |
     +----+----+----+----+----+----+          +-------------------------+
     | Y4 |941 | *  | 0  | #  | D  |          | 531   |     941         |
     +----+----+----+----+----+----+          +-------------------------+
          |    | X1 | X2 | X3 | X4 |          | 413   |     1209        |
          +----+----+----+----+--- +          +-------------------------+
                                              | 373   |     1336        |
                                              +-------------------------+
                                              | 338   |     1477        |
                                              +-------------------------+
                                              | 305   |     1633        |
                                              +-------------------------+
*/
  unsigned int X1=1209, X2=1336, X3=1477, X4=1633;
  unsigned int Y1=697,  Y2=770,  Y3=852,  Y4=941;
//******************************************************************************
void main()
 {...........................coming soon

 

Link al commento
Condividi su altri siti

Stefano di questo passo dovremmo aprirti una sezione dedicata 12F1572 :smile:

 

Comunque son lavoretti interessanti da cui si possono anche trarre spunti per altri lavori.:thumb_yello::clap:

Link al commento
Condividi su altri siti

Spunti che rimangono...specialmente a me...essendo disordinato molte volte cose che avevo fatto e poi perso le ho recuperate perché pubblicate sul forum :smile:

Generare i toni DTMF è stato semplice. Non volendo bruciare la memoria con funzioni complesse, ho usato 2 pwm comandati in periodo, mantenendo il duty cycle al 50% e scegliendo un clock che abbinato al fattore del prescaler dei pwm consenta di ottenere le frequenze richieste.

Con un clock a 8MHz e prescaler a /32 si ottiene che, ad esempio, caricando il valore 650 in PWMxPR viene generatala frequenza di 770,5 Hz cioè 0,5Hz in più di quanto necessario ma comunque in tolleranza rispetto la specifica.

Perchè funzioni il PWM in standard mode, il valore caricato in  PWMxPR deve essere uguale a quanto caricato il  PWMxPH e ciò semplifica la formula

7c0f15ac413119f7810990bfcaaf6fd6.JPG

 

dalla quale si ottiene che per avere un duty cycle del 50% è sufficiente che PWMxDC= PWMxPR/2

//******************************************************************************
// Comando PWM1-PWM2
//******************************************************************************
         PWM1PR = Dc1;         // PWM PERIOD COUNT REGISTER
         PWM1PH = Dc1;         // PWM PHASE  COUNT REGISTER
         PWM1DC = Dc1/2;       // RA0 OUT PWM[2]
         
         PWM2PR = Dc2;         // PWM PERIOD COUNT REGISTER
         PWM2PH = Dc2;         // PWM PHASE  COUNT REGISTER
         PWM2DC = Dc2/2;       // RA1 OUT PWM[1]

 

A Questo punto basta un case e prelevare dalla matrice X,Y i valori da assegnare ai due PWM,

      switch (numSel[i]){
       case 1:  Dc1=X1;
                Dc2=Y1;
                PWMLD=0x7;;
                break;

poi si mixano le due uscite con due condensatori e il tono è fatto.

Adesso viene la parte un po' più difficile

0a12a27cb1de0c5d8c112de9a2f6f8e3.png

- Contare gli impulsi

- distinguere l' interdigit, cioè il ritorno del disco compositore ed emettere il tono in questo istante

 

 

Modificato: da dott.cicala
Link al commento
Condividi su altri siti

Al momento non c'è ancora uno schema definitivo.

Nel frattempo.....come verificare se i toni generati sono corretti e se vengono riconosciuti....senza  impegnare la linea telefonica???

6cd35c03e7519a1c4a2334c5f7486433.jpg

Tutti i numeri hanno generato i rispettivi toni...e sono stati pure riconosciuti! :thumb_yello:

...alla faccia di tutti gli integratini e dei loro quarzi con frequenze balorde!:superlol:

Modificato: da dott.cicala
Link al commento
Condividi su altri siti

Crea un account o accedi per commentare

Devi essere un utente per poter lasciare un commento

Crea un account

Registrati per un nuovo account nella nostra comunità. è facile!

Registra un nuovo account

Accedi

Hai già un account? Accedi qui.

Accedi ora

×
×
  • Crea nuovo/a...