|
|
View previous topic :: View next topic |
Author |
Message |
Comiter
Joined: 26 May 2010 Posts: 2
|
Read multiple channels MCP3424 |
Posted: Sun Oct 10, 2010 3:02 pm |
|
|
Hi all!
I'm trying to read from different channels on a microchip MCP3424 ADC.
My problem are that I can't change between channels. When I read from only one channel (that is, compiles the SW with the other readings commented out), it works fine with different channels (only one at the time though). I've tried to read the channels in sequence, based on Timer1 interrupt, so that I read each channel once every 4th second, still the same result. The issue is that (when trying to read all channels) it reads the first value (the first time it enters the while loop) when the software runs, and that's it.
The code is found below:
Code: |
#include <18F87J11.h>
#device adc=10
#FUSES NOWDT
//#FUSES WDT128 //Watch Dog Timer uses 1:128 Postscale // Ca hvert 2 sec.
#FUSES HS //High speed Osc (> 4mhz for PCM/PCH) (>10mhz for PCD)
#FUSES NOPROTECT //Code not protected from reading
#use delay(clock=8000830)
#use i2c(Master, scl=PIN_C3,sda=PIN_C4,slow) //#use i2c(i2c1,MASTER,SCL=Device_SCL, SDA=Device_SDA,FAST=400000, FORCE_HW)//#use i2c(master, sda=PIN_J1, scl=PIN_J0,SLOW)
#use rs232(baud=19200, Parity=N, bits=8, stop=1, UART2)
#define ADCRead 0xDB
#define ADCWrite 0xDA
struct Verdier
{
float battSpenning;
float lading_Sol;
float lading_Vind;
float stromforbruk;
float alarmtimer;
int1 LavSpenningAlarm,LightOn;
//Variabler for display navigering
// Page 0 = Standard display
// Page 1 =
// Page 2 =
// Page 3 =
int pageNumber;
int WebastoPaa;
}maaling;
int1 skrivLcd,kalkuler, LCDInit;
#int_RTCC
void RTCC_isr(void)
{
// output_toggle(PIN_B6);
RTCISRTeller1++;
RTCISRTeller2++;
if(RTCISRTeller1 > 3){
RTCISRTeller1 =0;
skrivLCD = 1;
}
if(RTCISRTeller2>200){
RTCISRTeller2 = 0;
LCDInit = 1;
}
kalkuler = 1;
}
float ReadADC(int channel){
int8 HighBuffer,LowBuffer,Config,ack=0;
signed int16 value=0;
switch(channel){
case 1: i2c_start();
ack = i2c_write(ADCWrite); // Adress factory set at 1101 = 0xD
if(ack)
printf("Feil!!");
i2c_write(0x8B); //16bit mode, Gain = 8, one shot samplemode
i2c_stop();
delay_ms(5);// Wait for conversion to be finnished in oneshot mode
i2c_start();
i2c_write(ADCRead); //Set Read/Write to 1 for read
HighBuffer = i2c_read(1);
LowBuffer = i2c_read(1);
Config = i2c_read(1);
printf("Config: %x\n\r",Config);
while((Config&0x80)==1){Config = i2c_read(1);}; // Wait for finnish
i2c_stop(); // When conversion finnished
delay_ms(5);
i2c_start(); // Read new value
i2c_write(ADCRead); //Set Read/Write to 1 for read
HighBuffer = i2c_read(1);
LowBuffer = i2c_read(1);
Config = i2c_read(0);
i2c_stop();
delay_ms(5);
Value = make16(HighBuffer,LowBuffer);
return (float) Value;
break;
case 2: i2c_start();
i2c_write(ADCWrite); // Adress factory set at 1101 = 0xD
i2c_write(0xAB); //16bit mode, Gain = 8, one shot samplemode
i2c_stop();
delay_ms(5);
i2c_start();
i2c_write(ADCRead); //Set Read/Write to 1 for read
HighBuffer = i2c_read(1);
LowBuffer = i2c_read(1);
Config = i2c_read(1);
printf("Config: %x\n\r",Config);
while((Config&0x80)==1){Config = i2c_read(1);}; // Wait for finnish
i2c_stop(); // When conversion finnished
delay_ms(5);
i2c_start(); // Read new value
i2c_write(ADCRead); //Set Read/Write to 1 for read
HighBuffer = i2c_read(1);
LowBuffer = i2c_read(1);
Config = i2c_read(0);
i2c_stop();
delay_ms(5);
Value = make16(HighBuffer,LowBuffer);
return (float) Value;
break;
case 3: i2c_start();
i2c_write(ADCWrite); // Adress factory set at 1101 = 0xD
i2c_write(0xCB); //16bit mode, Gain = 8, one shot samplemode
i2c_stop();
delay_ms(5);
i2c_start();
i2c_write(ADCRead); //Set Read/Write to 1 for read
HighBuffer = i2c_read(1);
LowBuffer = i2c_read(1);
Config = i2c_read(1);
printf("Config: %x\n\r",Config);
while((Config&0x80)==1){Config = i2c_read(1);}; // Wait for finnish
i2c_stop(); // When conversion finnished
delay_ms(5);
i2c_start(); // Read new value
i2c_write(ADCRead); //Set Read/Write to 1 for read
HighBuffer = i2c_read(1);
LowBuffer = i2c_read(1);
Config = i2c_read(0);
i2c_stop();
delay_ms(5);
Value = make16(HighBuffer,LowBuffer);
return (float) Value;
break;
case 4: i2c_start();
i2c_write(ADCWrite); // Adress factory set at 1101 = 0xD
ack=i2c_write(0xE8); //16bit mode, Gain = 1, one shot samplemode
i2c_stop();
delay_ms(5);
i2c_start();
i2c_write(ADCRead); //Set Read/Write to 1 for read
HighBuffer = i2c_read(1);
LowBuffer = i2c_read(1);
Config = i2c_read(1);
printf("Config: %x\n\r",Config);
while((Config&0x80)==1){Config = i2c_read(1);}; // Wait for finnish
i2c_stop(); // When conversion finnished
delay_ms(5);
i2c_start(); // Read new value
i2c_write(ADCRead); //Set Read/Write to 1 for read
HighBuffer = i2c_read(1);
LowBuffer = i2c_read(1);
Config = i2c_read(0);
i2c_stop();
delay_ms(5);
Value = make16(HighBuffer,LowBuffer);
return (float) Value;
break;
default: break;
}
}
void lesLadingSol(struct Verdier *maaling){
maaling->lading_Sol = ReadADC(1);
maaling->lading_Sol = maaling->lading_Sol*0.0000078125;
maaling->lading_Sol = maaling->lading_Sol/0.00375;
// sol = spenning/0.00375;
}
void lesForbruk(struct Verdier *maaling){
maaling->stromforbruk = ReadADC(2);
maaling->stromforbruk = maaling->stromforbruk*0.0000078125;
maaling->stromforbruk = maaling->stromforbruk/0.00375;
// forbruk = spenning/0.00375;
}
void lesLadingVind(struct Verdier *maaling){
maaling->lading_Vind = ReadADC(3);
maaling->lading_Vind = maaling->lading_Vind*0.0000078125;
maaling->lading_Vind = maaling->lading_Vind/0.00375;
// vind = spenning/0.00375;
}
void LesBatteriSpenning(struct Verdier *maaling ){
maaling->battSpenning = ReadADC(4);
maaling->battSpenning = maaling->battSpenning*0.0000625;
maaling->battSpenning = maaling->battSpenning*-7.83;
// batteri = spenning*-7.83;
}
void main()
{
setup_oscillator(OSC_8MHZ|OSC_NORMAL|OSC_IDLE_MODE|OSC_PLL_OFF);
setup_adc_ports(NO_ANALOGS);
setup_adc(ADC_CLOCK_INTERNAL|ADC_TAD_MUL_2);
setup_psp(PMP_DISABLED);
// setup_spi(SPI_SS_DISABLED);
// setup_spi2(SPI_SS_DISABLED);
setup_timer_0(RTCC_INTERNAL|RTCC_DIV_32);
setup_timer_1(T1_INTERNAL|T1_DIV_BY_8);
setup_timer_2(T2_DIV_BY_16,255,16);
setup_timer_3(T3_DISABLED|T3_DIV_BY_1);
setup_timer_4(T4_DISABLED,0,1);
setup_comparator(FALSE);// This device COMP currently not supported by the PICWizard
enable_interrupts(INT_RTCC);
enable_interrupts(INT_TIMER1);
enable_interrupts(INT_TIMER2);
enable_interrupts(INT_RDA);
enable_interrupts(INT_RDA2);
enable_interrupts(GLOBAL);
i2cscan();
//General call to latch in address on adc.
i2c_start();
i2c_write(0x00);
i2c_write(0x04);
i2c_stop();
lcd_init();
initVars(&maaling);
BackLightControl(On);
Delay_ms(2000);
BackLightControl(Off);
setup_wdt(WDT_OFF);
while(1){
BackLightControl(On);
if(kalkuler){
kalkuler = 0;
lesLadingSol(&maaling);
lesForbruk(&maaling);
lesLadingVind(&maaling);
LesBatteriSpenning(&maaling);
//batteriAlarm(&maaling);
output_toggle(PIN_B6);
}
if(LCDInit){
LCDInit = 0;
lcd_init();
lcd_gotoxy(1,1);
printf(lcd_putc,"Batterisp: %f V",maaling.BattSpenning);
lcd_gotoxy(1,2);
printf(lcd_putc,"Forbruk: %f A",maaling.stromforbruk);
lcd_gotoxy(1,3);
printf(lcd_putc,"Lading Sol: %f A",maaling.lading_Sol);
lcd_gotoxy(1,4);
printf(lcd_putc,"Lading Vind: %f A",maaling.lading_Vind);
}
if(skrivLCD){
skrivLCD = 0;
lcd_gotoxy(1,1);
printf(lcd_putc,"Batterisp: %f V",maaling.BattSpenning);
lcd_gotoxy(1,2);
printf(lcd_putc,"Forbruk: %f A",maaling.stromforbruk);
lcd_gotoxy(1,3);
printf(lcd_putc,"Lading Sol: %f A",maaling.lading_Sol);
lcd_gotoxy(1,4);
printf(lcd_putc,"Lading Vind: %f A",maaling.lading_Vind);
printf("BatteriSp:%f V\n\r",maaling.BattSpenning);
printf("Strømforbruk:%f A\n\r",maaling.stromforbruk);
printf("Lading Sol:%f A\n\r",maaling.lading_Sol);
printf("Lading Vind:%f A\n\n\r",maaling.lading_Vind);
}
}
}
|
Any help are appreciated.
- Comiter |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Sun Oct 10, 2010 5:56 pm |
|
|
The MCP3424 data sheet says this, on the upper left side of page 19:
Quote: |
When the Master finds the RDY bit is cleared, it can send a
not-acknowledge (NAK) bit and a stop bit to exit the current
read operation and send a new read command for the latest
conversion data.
|
Your code is missing the part shown above in bold. You need to fix this
in all 4 cases, by adding the line shown in bold below to each case.
Quote: |
case 1: i2c_start();
ack = i2c_write(ADCWrite); // Adress factory set at 1101 = 0xD
if(ack)
printf("Feil!!");
i2c_write(0x8B); //16bit mode, Gain = 8, one shot samplemode
i2c_stop();
delay_ms(5);// Wait for conversion to be finnished in oneshot mode
i2c_start();
i2c_write(ADCRead); //Set Read/Write to 1 for read
HighBuffer = i2c_read(1);
LowBuffer = i2c_read(1);
Config = i2c_read(1);
printf("Config: %x\n\r",Config);
while((Config&0x80)==1){Config = i2c_read(1);};
Config = i2c_read(0); // Send a NACK to exit read operation
i2c_stop(); // When conversion finnished
delay_ms(5);
i2c_start(); // Read new value
i2c_write(ADCRead); //Set Read/Write to 1 for read
HighBuffer = i2c_read(1);
LowBuffer = i2c_read(1);
Config = i2c_read(0);
i2c_stop();
delay_ms(5);
Value = make16(HighBuffer,LowBuffer);
return (float) Value;
break;
|
Also, the test in the statement below isn't correct:
Quote: |
while((Config&0x80)==1){Config = i2c_read(1);};
|
If you do a bitwise AND on 'Config' and 0x80, you will get either 0x80
or 0x00. Neither of those results will ever be equal to 1. So as written,
your test will always fail and will drop out of the loop on the first pass.
You need to change it to this:
Code: | while(Config&0x80){Config = i2c_read(1);}; |
Now the test will be evaluated for True/False, and it will behave the way
that you want. You need to fix this in all 4 cases, also.
There might be other problems but I didn't look at it any more than this. |
|
|
Comiter
Joined: 26 May 2010 Posts: 2
|
|
Posted: Mon Oct 11, 2010 12:25 am |
|
|
Hi PCM programmer,
thank you very much for the swift reply!
I knew it was something in the datasheet I've missed! I'll do the changes you pointed out when I arrive back from work.
Also, I'll try to tidy up the code a bit, and remove all the delays (as these were added to investigate if there were timing issues going on).
- Comiter |
|
|
khwoo
Joined: 26 May 2009 Posts: 12
|
MCP3424 read 18 bits and send to PIC24HJ128GP206 |
Posted: Wed Oct 19, 2011 8:37 pm |
|
|
I saw the previous reply on the above topic.
And now I am doing the same thing which is
- to issue address/commend to MCP3424
- how the 18 bit data is read from MCP3424 to PIC24HJ128GP206
Same device - MCP3424 but PIC not the same.
Hope to get some guide on modifying the code above.
Thank you |
|
|
khwoo
Joined: 26 May 2009 Posts: 12
|
Re: Read multiple channels MCP3424 |
Posted: Sun Oct 23, 2011 7:13 pm |
|
|
Can the above code be applicable to PIC24HJ128GP206?
Does the above code allow MCP3424 to read 18 bits through 4 channels / Microchip PIC store the data in the registers? |
|
|
|
|
You cannot post new topics in this forum You cannot reply to topics in this forum You cannot edit your posts in this forum You cannot delete your posts in this forum You cannot vote in polls in this forum
|
Powered by phpBB © 2001, 2005 phpBB Group
|