Vai al contenuto
PLC Forum


Help Su Programma Scritto In C Con Pcwh - Acquisizione a/d. Dov'è che sbaglio?


fraderico

Messaggi consigliati

Ciao!

Ho un problema con la programmazione in c di un pic 877a.

Vi spiego che cosa deve fare il programma: ho 6 ingressi analogici che mi portano le informazioni di tensione e di temperatura di tre batterie(B1, B2 e B3).

Dopo che ricevo un segnale di abilitazione devo confrontare la tensione e la temp. della prima batteria con due riferimenti:

- se la tensione di batteria è + bassa del riferimento e se la temperatura è + alta di un altro riferimento il circuito deve selezionare la batteria successiva(nell'ordine B1-B2-B3-B1, ecc)

- Se invece le due condizioni sono rispettate devo selezionare la batteria tramite l'attivazione di un interruttore.

Ecco il mio listato(dovrei anche includere dei ritardi, però la farò in un secondo momento). Dov'è che sbaglio?

#include <16F877.h>

#define Vref 128 //valore di riferimento per la tensione di batteria esempio 128 corrisponde a 2,5 Volts

#define Tref 25 //valore di riferimento per la tenperatura di batteria esempio 25 corrisponde a 0,5 Volts

#device adc=8

void main ()

{

int tensione_B1,temperatura_B1,tensione_B2,temperatura_B2,tensione_B3,temperatura_B3, tensione_bus;

int GEST_BATT_ON, ALIM_PROCB_ON;

int SW1,SW2,SW3;

setup_adc_ports(ALL_ANALOG); //setta tutte le porte ad come analogiche

setup_adc(ADC_CLOCK_INTERNAL); //setta il clock come interno

if (GEST_BATT_ON ==1) //l'orologio ha contato 1 min

{

// acquisisce i sei valori analogici

set_adc_channel(0); // seleziona il canale 0

tensione_B1=read_adc(); //legge il valore della porta 0

set_adc_channel(1);

tensione_B2=read_adc();

set_adc_channel(2);

tensione_B3=read_adc();

set_adc_channel(3);

tensione_bus=read_adc(); // legge il valore della tensione sul bus

set_adc_channel(5);

temperatura_B1=read_adc();

set_adc_channel(6);

temperatura_B2=read_adc();

set_adc_channel(7); // seleziona il canale 6

temperatura_B3=read_adc();

do

{

if ((tensione_B1 > Vref) && (temperatura_B1<Tref)) // se tensione maggiore di Vref e temperatura minore di Tref

{

SW1= 1; // chiude l'interruttore tra la batteria B1 ed il bus

ALIM_PROCB_ON=1;

}

else if ((tensione_B2 > Vref) && (temperatura_B2<Tref))

{

SW2= 1;

ALIM_PROCB_ON=1;

}

else ((tensione_B3 > Vref) && (temperatura_B3<Tref))

{

SW3= 1;

ALIM_PROCB_ON=1;

}

}

while(TRUE);

}

} //end main

Link al commento
Condividi su altri siti


Non conosco esattamente le specifiche del compilatore che usi ma cosi com'è sarà difficile che ADC funzioni correttamente. Devi lasciare passare il tempo per l'acquisizione. Controlla tra le funzioni che hai a disposizione in libreria ci sarà BusyADC() o qualcosa del genere. Usala nel modo seguente:

while(BusyADC()); //polling periferica ADC

tensione_B1 =ReadADC();

......

fai lo stesso per le altre.

Ciao

Link al commento
Condividi su altri siti

Incompleto perchè la variabile GEST_BATT_ON chi la imposta? L'orologio? Ma dov'è il codice che lo gestisce?

Manca ogni riferimento agli ingressi e alle uscite digitali legate a GEST_BATT_ON, sw1, sw2 ed sw3.

Poi, il programma, ammesso che GEST_BATT_ON sia uno, fà una acquisizione ed entra in un ciclo do/while infinito dove le variabili tensione_B1, tensione_B2, ecc. non cambiano. Forse l'acquisizione volevi metterla dentro il ciclo?

Ciao.

Link al commento
Condividi su altri siti

Grazie a tutti voi per i suggerimenti, mi sono di grossissimo aiuto!

x wnc: utilizzo il compilatore della css e adesso vedrò di trovare qualche funzione che gestisca il tempo delle acquisizioni, se non la trovo utilizzo l'istruzione delay_ms()

x giacomo56: il programma, quando funzionerà correttamente, sarà modificato affinchè diventi una funzione. Questa, infatti, è parte di un programma più esteso.

La variabile GEST_BATT_ON sarà impostata da un orologio(il codice lo sta facendo un mio amico) e andrà ad '1' ogni volta che l'orologio conta 1 minuto.

Manca ogni riferimento agli ingressi e alle uscite digitali legate a GEST_BATT_ON, sw1, sw2 ed sw3.
Link al commento
Condividi su altri siti

Ok, adesso è più chiaro lo scopo del programma.

Quello che non ho capito è se il controllo delle batterie deve essere fatto una volta sola ogni minuto o se deve essere fatto di continuo dopo che GEST_BATT_ON và a uno.

L'ultimo codice che hai scritto equivale al seguente

while(TRUE)
{
  if ((tensione_B1 > Vref) && (temperatura_B1<Tref)) //se tensione maggiore di Vref e temperatura minore di Tref
  {
  SW1= 1; // chiude l'interruttore tra la batteria B1 ed il bus
  ALIM_PROCB_ON=1;
  break;
  }
}

Se una delle condizioni non è verificata non esci più dal ciclo, mentre invece devi controllare le altre batterie, o sbaglio?

Per quanto riguarda il ritardo da aggiungere nell'acquisizione ne devi mettere uno di qualche msec dopo che cambi canale, mentre per l'acquisizione ci pensa la funzione read_adc().

Ciao.

Link al commento
Condividi su altri siti

Ti ringrazio molto! Adesso penso di aver risolto il problema perchè visualizzando sul monitor e simulando gli ingressi il programma seleziona la batteria giusta.

Ora il programma è in forma di funzione e la richiamiamo ogni volta che dobbiamo verificare lo stato delle batterie.

#define Vref 128 //valore di riferimento per la tensione di batteria    esempio 128 corrisponde a 2,5 Volts

#define Tref 25 //valore di riferimento per la tenperatura di batteria  esempio 25 corrisponde a 0,5 Volts

#define SW1    PIN_RC0;

#define SW2    PIN_RC1;

#define SW3    PIN_RC2;

void gestione_batterie() {

int tensione_B1,temperatura_B1;

int tensione_B2,temperatura_B2;

int tensione_B3,temperatura_B3;

int tensione_bus;

set_adc_channel(0);

delay_us(10);

tensione_B1=read_adc();

set_adc_channel(1);

delay_us(10);

tensione_B2=read_adc();

set_adc_channel(2);

delay_us(10);

tensione_B3=read_adc();

set_adc_channel(3);

delay_us(10);

tensione_bus=read_adc();

set_adc_channel(5);

delay_us(10);

temperatura_B1=read_adc();

set_adc_channel(6);

delay_us(10);

temperatura_B2=read_adc();

set_adc_channel(7);

delay_us(10);

temperatura_B3=read_adc();

output_low(SW1);

output_low(SW2);

output_low(SW3);

if ((tensione_B1 > Vref) && (temperatura_B1<Tref)) {

      output_high(SW1);

}

else if ((tensione_B2 > Vref) && (temperatura_B2<Tref)) {

      output_high(SW2);

}

else if ((tensione_B3 > Vref) && (temperatura_B3<Tref)) {

      output_high(SW3);

}

}

}

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...