|
|
View previous topic :: View next topic |
Author |
Message |
Wolf
Joined: 23 Sep 2011 Posts: 32
|
Printf Code |
Posted: Sun Feb 24, 2013 12:10 am |
|
|
Hey everyone...
I know this is going to sound dumb, but I'm unable to get stuff printed to my terminal screen using PIC18F4431, I'm use to working with PIC16F877 so its a big change. I'm doing some variable frequency drive experiments and I need to see how interrupts affect PWM patterns when I get this chip controlled by SPI or I2C signals. But before I could do that, I need my printf's and external interrupts working. Here is my code...
Code: |
#include <18f4431.h>
#device ICD = TRUE
#fuses HS,NOWDT,NOPROTECT
#use delay(clock=8000000)
#use rs232(baud=9600, xmit=PIN_C6, rcv=PIN_C7)
#INT_EXT
void isr_ext0() {
printf("Interupt Test\n\r");
return;
}
void main() {
int16 intADCValue, intPeriod, intSpeed;
int16 intAdjust = 0, intFBInital, intFBFinal;
int16 intCounter = 0;
enable_interrupts(INT_EXT);
setup_power_pwm_pins(PWM_COMPLEMENTARY,PWM_COMPLEMENTARY,PWM_COMPLEMENTARY, PWM_OFF);
setup_adc_ports(ADC_CONT_A | ADC_WHEN_PPWM | VSS_VDD);
setup_adc(ADC_CLOCK_INTERNAL);
printf("Start Test\n\r");
while (1) {
printf("Line test\n\r");
set_adc_channel(0); // Select ADC Channel 1
intFBInital = read_adc();
set_adc_channel(1); // Select ADC Channel 1
intADCValue = read_adc();
intPeriod = (intADCValue/20) + 9; // Set PR2 for Frequency
intSpeed = 511 - ((1023 - intADCValue)/2); // Set User Specified Speed
setup_power_pwm(PWM_CLOCK_DIV_128 | PWM_FREE_RUN, 1, 0, intPeriod, 0, 1, 0);
set_power_pwm0_duty(intAdjust+57+intSpeed); // Phase U PWM Duty Setting
set_power_pwm2_duty(intAdjust+29+intSpeed/4); // Phase V PWM Duty Setting
set_power_pwm4_duty(intAdjust+1); // Phase W PWM Duty Setting
// Phase Segment #2
set_power_pwm0_duty(intAdjust+57+intSpeed); // Phase U PWM Duty Setting
set_power_pwm2_duty(intAdjust+43+intSpeed/2); // Phase V PWM Duty Setting
set_power_pwm4_duty(intAdjust+1); // Phase W PWM Duty Setting
// Phase Segment #3
set_power_pwm0_duty(intAdjust+43+intSpeed/2); // Phase U PWM Duty Setting
set_power_pwm2_duty(intAdjust+57+intSpeed); // Phase V PWM Duty Setting
set_power_pwm4_duty(intAdjust+1); // Phase W PWM Duty Setting
// Phase Segment #4
set_power_pwm0_duty(intAdjust+29+intSpeed/4); // Phase U PWM Duty Setting
set_power_pwm2_duty(intAdjust+57+intSpeed); // Phase V PWM Duty Setting
set_power_pwm4_duty(intAdjust+14+intSpeed/6); // Phase W PWM Duty Setting
// Phase Segment #5
set_power_pwm0_duty(intAdjust+14+intSpeed/6); // Phase U PWM Duty Setting
set_power_pwm2_duty(intAdjust+57+intSpeed); // Phase V PWM Duty Setting
set_power_pwm4_duty(intAdjust+29+intSpeed/4); // Phase W PWM Duty Setting
// Phase Segment #6
set_power_pwm0_duty(intAdjust+1); // Phase U PWM Duty Setting
set_power_pwm2_duty(intAdjust+57+intSpeed); // Phase V PWM Duty Setting
set_power_pwm4_duty(intAdjust+43+intSpeed/2); // Phase W PWM Duty Setting
// Phase Segment #7
set_power_pwm0_duty(intAdjust+1); // Phase U PWM Duty Setting
set_power_pwm2_duty(intAdjust+43+intSpeed/2); // Phase V PWM Duty Setting
set_power_pwm4_duty(intAdjust+57+intSpeed); // Phase W PWM Duty Setting
// Phase Segment #8
set_power_pwm0_duty(intAdjust+1); // Phase U PWM Duty Setting
set_power_pwm2_duty(intAdjust+29+intSpeed/4); // Phase V PWM Duty Setting
set_power_pwm4_duty(intAdjust+57+intSpeed); // Phase W PWM Duty Setting
// Phase Segment #9
set_power_pwm0_duty(intAdjust+14+intSpeed/6); // Phase U PWM Duty Setting
set_power_pwm2_duty(intAdjust+14+intSpeed/6); // Phase V PWM Duty Setting
set_power_pwm4_duty(intAdjust+intSpeed); // Phase W PWM Duty Setting
// Phase Segment #10
set_power_pwm0_duty(intAdjust+29+intSpeed/4); // Phase U PWM Duty Setting
set_power_pwm2_duty(intAdjust+1); // Phase V PWM Duty Setting
set_power_pwm4_duty(intAdjust+57+intSpeed); // Phase W PWM Duty Setting
// Phase Segment #11
set_power_pwm0_duty(intAdjust+43+intSpeed/2); // Phase U PWM Duty Setting
set_power_pwm2_duty(intAdjust+1); // Phase V PWM Duty Setting
set_power_pwm4_duty(intAdjust+43+intSpeed/2); // Phase W PWM Duty Setting
// Phase Segment #12
set_power_pwm0_duty(intAdjust+57+intSpeed); // Phase U PWM Duty Setting
set_power_pwm2_duty(intAdjust+1); // Phase V PWM Duty Setting
set_power_pwm4_duty(intAdjust+29+intSpeed/4); // Phase W PWM Duty Setting
// Phase Segment #13
set_power_pwm0_duty(intAdjust+57+intSpeed); // Phase U PWM Duty Setting
set_power_pwm2_duty(intAdjust+14+intSpeed/6); // Phase V PWM Duty Setting
set_power_pwm4_duty(intAdjust+14+intSpeed/6); // Phase W PWM Duty Setting
intCounter++;
if (intCounter > 1799) {
set_adc_channel(0); // Select ADC Channel 0
intFBFinal = read_adc(); // Read Feedback from ADC
intAdjust = intFBInital - intFBFinal; // Calculate Speed Adjust
intCounter = 0;
}
}
}
|
Good news is the PWM stuff works just like I want it to, I modified someone's CCS code to see how it works and stuff. This is where I derived this program off of http://www.ccsinfo.com/forum/viewtopic.php?p=172029. However this is the most frustrating pic I had ever worked with yet cause it doesn't play nice like something such as 18F2620 for instance. If someone can please point me in the right direction with the printf and using interrupt 0, I would be grateful. |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Sun Feb 24, 2013 1:02 am |
|
|
The reason interrupts don't work is because you're missing a line to
enable GLOBAL interrupts. |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19520
|
|
Posted: Sun Feb 24, 2013 2:25 am |
|
|
You are going to need the SSP_RD fuse. Currently the SSP is on the pins you are trying to use for the serial.
Also, you should _always_ have 'ERRORS' in your RS232 declaration when using the hardware UART. This applies to the 16F877 as well....
The rule here should be that ERRORS _must_ be present, unless _you_ are explicitly handling errors yourself.
Turn off the FSCM (NOFSCM fuse). makes it difficult to be sure your oscillator is running correctly, when testing, since the chip will keep working, using the internal oscillator. Print's then will give garbage.
Add PUT. You should always use this (or the two speed start up) with a crystal.
Is ADC_CLOCK_INTERNAL recommended at your clock rate/setup. Table20-2 in the data sheet, what does note3 say?.
You are telling the ADC to both automatically convert when the power PWM operates, then sample continuously, then overriding this and triggering another reading. If you want the reading it has automatically taken read_adc(ADC_READ_ONLY), is the command to return the reading already triggered. If you don't want this, then change your ADC setup. Unless you program Tacq into the ADC setup, _you_ must wait this time between selecting the channel, and taking the reading. It appears from the way you are doing the readings, you don't want ADC_CONT_A, or ADC_WHEN_PPWM in the setup at all. You also have not enabled the ADC pins to the multiplexer sAN0, sAN1, given you read these channels later....
Best Wishes |
|
|
Wolf
Joined: 23 Sep 2011 Posts: 32
|
|
Posted: Sun Feb 24, 2013 3:11 am |
|
|
Well first thing is, I discovered why I wasn't getting printf to work and that was because the ICD3 wasn't programming the chip right. It was picking up EMI from my video cards and now got it to print to my screen no problem
However, Interrupts still jam up. When I try to call them, they either get stuck and affect the complementary PWM settings. Also NOFSCM isn't a command recognized by the compiler cause I get this...
Quote: |
Error#111 Unknown keyword in #FUSES "NOFSCM"
|
Also table 20-2 brings me to the baud rate calculator table on page 222. I was able to get the Analog stuff working with ADC_CLOCK_INTERNAL it was adjusting the frequencies on the PWM stuff nicely
I don't understand what you mean by add PUT sorry. |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19520
|
|
Posted: Sun Feb 24, 2013 3:52 am |
|
|
Yes, CCS insist on calling the fuse FCMEN, instead of the Microchip name. So, NOFCMEN.
Test your interrupts a different way. Just set a flag in the interrupt, and have the main code print when this is set (and clear it). There is a problem that having the print in the interrupt, will result in interrupts being disabled in the main, whenever print's are called.
It sounds as if the supply rail on your board may be lacking good HF blocking close to the chip. This is always essential, but even more so when using PWM's.
Best Wishes |
|
|
Wolf
Joined: 23 Sep 2011 Posts: 32
|
|
Posted: Sun Feb 24, 2013 5:18 am |
|
|
Ya, now my interrupts don't work at all
Code: |
/*
* File: Test.c
* Author: Administrator
*
* Created on February 22, 2013, 9:15 PM
*/
#include <18f4431.h>
#device ICD = TRUE
//#fuses INTRC_IO,NOWDT,NOPROTECT,NOMCLR
#fuses HS, NOWDT, NOPROTECT, SSP_RD, NOFCMEN, NOWDT //, INTRC_IO
#use delay(clock=8000000)
#use rs232(baud=9600, xmit=PIN_C6, rcv=PIN_C7, ERRORS)
unsigned char uchIntTest;
#int_rb
void isr_ext0() {
uchIntTest = 1;
//clear_interrupts(INT_EXT);
return;
}
void main() {
int16 intADCValue, intPeriod, intSpeed;
int16 intAdjust = 0, intFBInital, intFBFinal;
int16 intCounter = 0;
//set_tris_c(0x08);
uchIntTest = 0;
setup_power_pwm_pins(PWM_COMPLEMENTARY,PWM_COMPLEMENTARY,PWM_COMPLEMENTARY, PWM_OFF);
setup_adc_ports(ADC_CONT_A | ADC_WHEN_PPWM | VSS_VDD);
setup_adc(ADC_CLOCK_INTERNAL);
ext_int_edge(H_TO_L);
enable_interrupts(int_rb);
enable_interrupts(global);
delay_ms(1000);
printf("Start Test\n\r");
while (1) {
if (uchIntTest == 1) {
printf("Interupt Test\n\r");
uchIntTest = 0;
}
set_adc_channel(0); // Select ADC Channel 1
intFBInital = read_adc();
set_adc_channel(1); // Select ADC Channel 1
intADCValue = read_adc();
intPeriod = (intADCValue/20) + 9; // Set PR2 for Frequency
intSpeed = 511 - ((1023 - intADCValue)/2); // Set User Specified Speed
setup_power_pwm(PWM_CLOCK_DIV_128 | PWM_FREE_RUN, 1, 0, intPeriod, 0, 1, 0);
set_power_pwm0_duty(intAdjust+57+intSpeed); // Phase U PWM Duty Setting
set_power_pwm2_duty(intAdjust+29+intSpeed/4); // Phase V PWM Duty Setting
set_power_pwm4_duty(intAdjust+1); // Phase W PWM Duty Setting
// Phase Segment #2
set_power_pwm0_duty(intAdjust+57+intSpeed); // Phase U PWM Duty Setting
set_power_pwm2_duty(intAdjust+43+intSpeed/2); // Phase V PWM Duty Setting
set_power_pwm4_duty(intAdjust+1); // Phase W PWM Duty Setting
// Phase Segment #3
set_power_pwm0_duty(intAdjust+43+intSpeed/2); // Phase U PWM Duty Setting
set_power_pwm2_duty(intAdjust+57+intSpeed); // Phase V PWM Duty Setting
set_power_pwm4_duty(intAdjust+1); // Phase W PWM Duty Setting
// Phase Segment #4
set_power_pwm0_duty(intAdjust+29+intSpeed/4); // Phase U PWM Duty Setting
set_power_pwm2_duty(intAdjust+57+intSpeed); // Phase V PWM Duty Setting
set_power_pwm4_duty(intAdjust+14+intSpeed/6); // Phase W PWM Duty Setting
// Phase Segment #5
set_power_pwm0_duty(intAdjust+14+intSpeed/6); // Phase U PWM Duty Setting
set_power_pwm2_duty(intAdjust+57+intSpeed); // Phase V PWM Duty Setting
set_power_pwm4_duty(intAdjust+29+intSpeed/4); // Phase W PWM Duty Setting
// Phase Segment #6
set_power_pwm0_duty(intAdjust+1); // Phase U PWM Duty Setting
set_power_pwm2_duty(intAdjust+57+intSpeed); // Phase V PWM Duty Setting
set_power_pwm4_duty(intAdjust+43+intSpeed/2); // Phase W PWM Duty Setting
// Phase Segment #7
set_power_pwm0_duty(intAdjust+1); // Phase U PWM Duty Setting
set_power_pwm2_duty(intAdjust+43+intSpeed/2); // Phase V PWM Duty Setting
set_power_pwm4_duty(intAdjust+57+intSpeed); // Phase W PWM Duty Setting
// Phase Segment #8
set_power_pwm0_duty(intAdjust+1); // Phase U PWM Duty Setting
set_power_pwm2_duty(intAdjust+29+intSpeed/4); // Phase V PWM Duty Setting
set_power_pwm4_duty(intAdjust+57+intSpeed); // Phase W PWM Duty Setting
// Phase Segment #9
set_power_pwm0_duty(intAdjust+14+intSpeed/6); // Phase U PWM Duty Setting
set_power_pwm2_duty(intAdjust+14+intSpeed/6); // Phase V PWM Duty Setting
set_power_pwm4_duty(intAdjust+intSpeed); // Phase W PWM Duty Setting
// Phase Segment #10
set_power_pwm0_duty(intAdjust+29+intSpeed/4); // Phase U PWM Duty Setting
set_power_pwm2_duty(intAdjust+1); // Phase V PWM Duty Setting
set_power_pwm4_duty(intAdjust+57+intSpeed); // Phase W PWM Duty Setting
// Phase Segment #11
set_power_pwm0_duty(intAdjust+43+intSpeed/2); // Phase U PWM Duty Setting
set_power_pwm2_duty(intAdjust+1); // Phase V PWM Duty Setting
set_power_pwm4_duty(intAdjust+43+intSpeed/2); // Phase W PWM Duty Setting
// Phase Segment #12
set_power_pwm0_duty(intAdjust+57+intSpeed); // Phase U PWM Duty Setting
set_power_pwm2_duty(intAdjust+1); // Phase V PWM Duty Setting
set_power_pwm4_duty(intAdjust+29+intSpeed/4); // Phase W PWM Duty Setting
// Phase Segment #13
set_power_pwm0_duty(intAdjust+57+intSpeed); // Phase U PWM Duty Setting
set_power_pwm2_duty(intAdjust+14+intSpeed/6); // Phase V PWM Duty Setting
set_power_pwm4_duty(intAdjust+14+intSpeed/6); // Phase W PWM Duty Setting
intCounter++;
if (intCounter > 1799) {
set_adc_channel(0); // Select ADC Channel 0
intFBFinal = read_adc(); // Read Feedback from ADC
intAdjust = intFBInital - intFBFinal; // Calculate Speed Adjust
intCounter = 0;
}
}
}
|
Everytime I go to enable any interrupt at all, it jams the PWM slay ride that it does
Also you can see my breadboard here:
Breadboard 1 Image
Breadboard 2 Image
This is what the pattern is suppose to look like on the scope:
Scope |
|
|
necati
Joined: 12 Sep 2003 Posts: 37 Location: istanbul
|
pwm |
Posted: Sun Feb 24, 2013 7:00 am |
|
|
/*
* File: Test.c
* Author: Administrator
*
* Created on February 22, 2013, 9:15 PM
*/
#include <18f4431.h>
#device ADC=10
#device *=16
//#fuses INTRC_IO,NOWDT,NOPROTECT,NOMCLR
#fuses XT, NOWDT, NOPROTECT,SSP_RD,NOFCMEN,NOWDT //, INTRC_IO
#use delay(clock=8000000)
#use rs232(baud=9600, xmit=PIN_C6, rcv=PIN_C7, ERRORS)
unsigned char uchIntTest;
#int_rb
void isr_ext0() {
uchIntTest = 1;
//clear_interrupts(INT_EXT);
return;
}
void main() {
SET_TRIS_A (0b11111111);
SET_TRIS_B (0b00000000);
SET_TRIS_C (0b10000000);
SET_TRIS_D (0b11111111);
int16 intADCValue, intPeriod, intSpeed;
int16 intAdjust = 0, intFBInital, intFBFinal;
int16 intCounter = 0;
//set_tris_c(0x08);
uchIntTest = 0;
setup_power_pwm_pins(PWM_COMPLEMENTARY,PWM_COMPLEMENTARY,PWM_COMPLEMENTARY, PWM_OFF);
setup_adc_ports(ADC_CONT_A | ADC_WHEN_PPWM | VSS_VDD);
setup_adc(ADC_CLOCK_INTERNAL);
SETUP_ADC(sAN0 | sAN1);
ext_int_edge(H_TO_L);
enable_interrupts(int_rb);
enable_interrupts(global);
delay_ms(1000);
printf("Start Test\n\r");
while (true) {
if (uchIntTest == 1) {
printf("Interupt Test\n\r");
uchIntTest = 0;
}
set_adc_channel(0);// Select ADC Channel 1
delay_us(10);
intFBInital = read_adc();
set_adc_channel(1); // Select ADC Channel 1
delay_us(10);
intADCValue = read_adc();
delay_us(10);
intPeriod = (intADCValue/20) + 9; // Set PR2 for Frequency
intSpeed = 511 - ((1023 - intADCValue)/2); // Set User Specified Speed
//printf("%4ld %4ld \n\r",intFBInital,intSpeed);
setup_power_pwm(PWM_CLOCK_DIV_128 | PWM_FREE_RUN, 1, 0, intPeriod, 0, 1, 0);
set_power_pwm0_duty(intAdjust+57+intSpeed); // Phase U PWM Duty Setting
set_power_pwm2_duty(intAdjust+29+intSpeed/4); // Phase V PWM Duty Setting
set_power_pwm4_duty(intAdjust+1); // Phase W PWM Duty Setting
// Phase Segment #2
set_power_pwm0_duty(intAdjust+57+intSpeed); // Phase U PWM Duty Setting
set_power_pwm2_duty(intAdjust+43+intSpeed/2); // Phase V PWM Duty Setting
set_power_pwm4_duty(intAdjust+1); // Phase W PWM Duty Setting
// Phase Segment #3
set_power_pwm0_duty(intAdjust+43+intSpeed/2); // Phase U PWM Duty Setting
set_power_pwm2_duty(intAdjust+57+intSpeed); // Phase V PWM Duty Setting
set_power_pwm4_duty(intAdjust+1); // Phase W PWM Duty Setting
// Phase Segment #4
set_power_pwm0_duty(intAdjust+29+intSpeed/4); // Phase U PWM Duty Setting
set_power_pwm2_duty(intAdjust+57+intSpeed); // Phase V PWM Duty Setting
set_power_pwm4_duty(intAdjust+14+intSpeed/6); // Phase W PWM Duty Setting
// Phase Segment #5
set_power_pwm0_duty(intAdjust+14+intSpeed/6); // Phase U PWM Duty Setting
set_power_pwm2_duty(intAdjust+57+intSpeed); // Phase V PWM Duty Setting
set_power_pwm4_duty(intAdjust+29+intSpeed/4); // Phase W PWM Duty Setting
// Phase Segment #6
set_power_pwm0_duty(intAdjust+1); // Phase U PWM Duty Setting
set_power_pwm2_duty(intAdjust+57+intSpeed); // Phase V PWM Duty Setting
set_power_pwm4_duty(intAdjust+43+intSpeed/2); // Phase W PWM Duty Setting
// Phase Segment #7
set_power_pwm0_duty(intAdjust+1); // Phase U PWM Duty Setting
set_power_pwm2_duty(intAdjust+43+intSpeed/2); // Phase V PWM Duty Setting
set_power_pwm4_duty(intAdjust+57+intSpeed); // Phase W PWM Duty Setting
// Phase Segment #8
set_power_pwm0_duty(intAdjust+1); // Phase U PWM Duty Setting
set_power_pwm2_duty(intAdjust+29+intSpeed/4); // Phase V PWM Duty Setting
set_power_pwm4_duty(intAdjust+57+intSpeed); // Phase W PWM Duty Setting
// Phase Segment #9
set_power_pwm0_duty(intAdjust+14+intSpeed/6); // Phase U PWM Duty Setting
set_power_pwm2_duty(intAdjust+14+intSpeed/6); // Phase V PWM Duty Setting
set_power_pwm4_duty(intAdjust+intSpeed); // Phase W PWM Duty Setting
// Phase Segment #10
set_power_pwm0_duty(intAdjust+29+intSpeed/4); // Phase U PWM Duty Setting
set_power_pwm2_duty(intAdjust+1); // Phase V PWM Duty Setting
set_power_pwm4_duty(intAdjust+57+intSpeed); // Phase W PWM Duty Setting
// Phase Segment #11
set_power_pwm0_duty(intAdjust+43+intSpeed/2); // Phase U PWM Duty Setting
set_power_pwm2_duty(intAdjust+1); // Phase V PWM Duty Setting
set_power_pwm4_duty(intAdjust+43+intSpeed/2); // Phase W PWM Duty Setting
// Phase Segment #12
set_power_pwm0_duty(intAdjust+57+intSpeed); // Phase U PWM Duty Setting
set_power_pwm2_duty(intAdjust+1); // Phase V PWM Duty Setting
set_power_pwm4_duty(intAdjust+29+intSpeed/4); // Phase W PWM Duty Setting
// Phase Segment #13
set_power_pwm0_duty(intAdjust+57+intSpeed); // Phase U PWM Duty Setting
set_power_pwm2_duty(intAdjust+14+intSpeed/6); // Phase V PWM Duty Setting
set_power_pwm4_duty(intAdjust+14+intSpeed/6); // Phase W PWM Duty Setting
intCounter++;
if (intCounter > 1799) {
set_adc_channel(0);// Select ADC Channel 0
delay_us(10);
intFBFinal = read_adc();// Read Feedback from ADC
delay_us(10);
intAdjust = intFBInital - intFBFinal; // Calculate Speed Adjust
intCounter = 0;
}
}
}
//pin11 vdd
//pin12 vss |
|
|
Wolf
Joined: 23 Sep 2011 Posts: 32
|
|
Posted: Sun Feb 24, 2013 7:39 am |
|
|
Interesting modifications, I do have to say it runs smoother to some extent however I still can't trigger the interrupt, INT0 (RC3 at Pin 18) it has a 270 ohm resister going to that pin and then to +5 volts, I would expect that when I short that resistor to ground it will pull it to the interrupt but it doesn't.
Also the delay_us(10); into the code adds instability to the setup. You see what happens is at various points of the analog readings, PWM0 and 4 will lock up high with PWM 2 still pulsing. Now if you connect that to an IGBT array, it will cause the array to over heat, short circuit and possibly explode (depending on what motor is used). |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19520
|
|
Posted: Sun Feb 24, 2013 8:46 am |
|
|
The code posted by Necati, uses INT_RB, not INT_EXT. This will cause major problems as posted, since it'll never exit the interrupt. With INT_RB, the interrupt _cannot be cleared_ until the port is read. Hence once triggered, the code will stay in the interrupt for ever. You need to read the port in the interrupt, and the trigger is any of pins B4 to B7. You'd also need to read the port before enabling the interrupt.
INT_EXT, is easier for what you want.
Always with the chips, look at what else is on the pin, and make sure that this doesn't interfere with what you want to do. The timer1 oscillator _output_ is also on the C0 pin, and can override it's use as an input. setup_timer1(T1_DISABLED);
It should default to this, but always better to be safe.
You are still using ADC_CLOCK_INTERNAL. This is still _wrong_.
Best Wishes |
|
|
Wolf
Joined: 23 Sep 2011 Posts: 32
|
|
Posted: Sun Feb 24, 2013 9:13 am |
|
|
Ok, I'm looking at this PIC18F4431 Datasheet. You mentioned look at note 3 of table 20-2, and that talks about baud rate. I'm looking at register 21-3 where it talks about ADC clock's and I cannot understand or see how that is wrong for the life of me....are you and I looking at different datasheets or something? Or am I just lacking sleep and what i'm really looking for isn't popping out at me? |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19520
|
|
Posted: Sun Feb 24, 2013 10:27 am |
|
|
Probably an older data sheet in my library. Look for the phrase:
"TAD vs. DEVICE OPERATING FREQUENCIES"
This is the title of the table. The note is below it. This applies to just about _all_ PIC's. Basically, if you use the internal clock, the sampling is asynchronous to the master clock. With the noise on the supply rails introduced by the PIC itself, this results in massively degrading the accuracy of the ADC, unless you stop the clock to do the sampling (put the chip to sleep). With a PWM, you obviously can't do this.
It is a very common error, several of the CCS examples also miss this one...
Best Wishes |
|
|
Wolf
Joined: 23 Sep 2011 Posts: 32
|
|
Posted: Sun Feb 24, 2013 4:25 pm |
|
|
Ok, so I changed the code to ADC_CLOCK_DIV_2 as you can see...
Code: |
/*
* File: Test.c
* Author: Administrator
*
* Created on February 22, 2013, 9:15 PM
*/
#include <18f4431.h>
#device ICD=TRUE
#device ADC=10
#device *=16
//#fuses INTRC_IO,NOWDT,NOPROTECT,NOMCLR
#fuses HS, NOWDT, NOPROTECT, SSP_RD, NOFCMEN, NOWDT //, INTRC_IO
#use delay(clock=8000000)
#use rs232(baud=9600, xmit=PIN_C6, rcv=PIN_C7, ERRORS)
unsigned char uchIntTest;
#INT_EXT
void isr_ext0() {
uchIntTest = 1;
output_high(PIN_C0);
//delay_ms(2000);
//output_low(PIN_C0);
//clear_interrupts(INT_EXT);
return;
}
void main() {
int intInterruptCounter = 0;
int16 intADCValue, intPeriod, intSpeed;
int16 intAdjust = 0, intFBInital, intFBFinal;
int16 intCounter = 0;
set_tris_a(0xFF);
set_tris_b(0x00);
set_tris_c(0x88);
set_tris_d(0xFF);
uchIntTest = 0;
setup_power_pwm_pins(PWM_COMPLEMENTARY,PWM_COMPLEMENTARY,PWM_COMPLEMENTARY, PWM_OFF);
setup_adc_ports(ADC_CONT_A | ADC_WHEN_PPWM | VSS_VDD);
//setup_adc(ADC_CLOCK_INTERNAL);
setup_adc(ADC_CLOCK_DIV_2);
setup_adc(sAN0 | sAN1);
ext_int_edge(H_TO_L);
enable_interrupts(INT_EXT);
enable_interrupts(global);
delay_ms(1000);
printf("Start Test\n\r");
while (1) {
if (uchIntTest == 1) {
intInterruptCounter++;
printf("Interrupt %d. Per= %d, S= %d, Analog= %d\n\r", intInterruptCounter, (int)intPeriod, (int)intSpeed, (int)intADCValue);
output_low(PIN_C0);
uchIntTest = 0;
}
set_adc_channel(0); // Select ADC Channel 0
delay_us(10);
intFBInital = read_adc();
set_adc_channel(1); // Select ADC Channel 1
delay_us(10);
intADCValue = read_adc();
intPeriod = (intADCValue/20) + 9; // Set PR2 for Frequency
intSpeed = 511 - ((1023 - intADCValue)/2); // Set User Specified Speed
setup_power_pwm(PWM_CLOCK_DIV_128 | PWM_FREE_RUN, 1, 0, intPeriod, 0, 1, 0);
set_power_pwm0_duty(intAdjust+57+intSpeed); // Phase U PWM Duty Setting
set_power_pwm2_duty(intAdjust+29+intSpeed/4); // Phase V PWM Duty Setting
set_power_pwm4_duty(intAdjust+1); // Phase W PWM Duty Setting
// Phase Segment #2
set_power_pwm0_duty(intAdjust+57+intSpeed); // Phase U PWM Duty Setting
set_power_pwm2_duty(intAdjust+43+intSpeed/2); // Phase V PWM Duty Setting
set_power_pwm4_duty(intAdjust+1); // Phase W PWM Duty Setting
// Phase Segment #3
set_power_pwm0_duty(intAdjust+43+intSpeed/2); // Phase U PWM Duty Setting
set_power_pwm2_duty(intAdjust+57+intSpeed); // Phase V PWM Duty Setting
set_power_pwm4_duty(intAdjust+1); // Phase W PWM Duty Setting
// Phase Segment #4
set_power_pwm0_duty(intAdjust+29+intSpeed/4); // Phase U PWM Duty Setting
set_power_pwm2_duty(intAdjust+57+intSpeed); // Phase V PWM Duty Setting
set_power_pwm4_duty(intAdjust+14+intSpeed/6); // Phase W PWM Duty Setting
// Phase Segment #5
set_power_pwm0_duty(intAdjust+14+intSpeed/6); // Phase U PWM Duty Setting
set_power_pwm2_duty(intAdjust+57+intSpeed); // Phase V PWM Duty Setting
set_power_pwm4_duty(intAdjust+29+intSpeed/4); // Phase W PWM Duty Setting
// Phase Segment #6
set_power_pwm0_duty(intAdjust+1); // Phase U PWM Duty Setting
set_power_pwm2_duty(intAdjust+57+intSpeed); // Phase V PWM Duty Setting
set_power_pwm4_duty(intAdjust+43+intSpeed/2); // Phase W PWM Duty Setting
// Phase Segment #7
set_power_pwm0_duty(intAdjust+1); // Phase U PWM Duty Setting
set_power_pwm2_duty(intAdjust+43+intSpeed/2); // Phase V PWM Duty Setting
set_power_pwm4_duty(intAdjust+57+intSpeed); // Phase W PWM Duty Setting
// Phase Segment #8
set_power_pwm0_duty(intAdjust+1); // Phase U PWM Duty Setting
set_power_pwm2_duty(intAdjust+29+intSpeed/4); // Phase V PWM Duty Setting
set_power_pwm4_duty(intAdjust+57+intSpeed); // Phase W PWM Duty Setting
// Phase Segment #9
set_power_pwm0_duty(intAdjust+14+intSpeed/6); // Phase U PWM Duty Setting
set_power_pwm2_duty(intAdjust+14+intSpeed/6); // Phase V PWM Duty Setting
set_power_pwm4_duty(intAdjust+intSpeed); // Phase W PWM Duty Setting
// Phase Segment #10
set_power_pwm0_duty(intAdjust+29+intSpeed/4); // Phase U PWM Duty Setting
set_power_pwm2_duty(intAdjust+1); // Phase V PWM Duty Setting
set_power_pwm4_duty(intAdjust+57+intSpeed); // Phase W PWM Duty Setting
// Phase Segment #11
set_power_pwm0_duty(intAdjust+43+intSpeed/2); // Phase U PWM Duty Setting
set_power_pwm2_duty(intAdjust+1); // Phase V PWM Duty Setting
set_power_pwm4_duty(intAdjust+43+intSpeed/2); // Phase W PWM Duty Setting
// Phase Segment #12
set_power_pwm0_duty(intAdjust+57+intSpeed); // Phase U PWM Duty Setting
set_power_pwm2_duty(intAdjust+1); // Phase V PWM Duty Setting
set_power_pwm4_duty(intAdjust+29+intSpeed/4); // Phase W PWM Duty Setting
// Phase Segment #13
set_power_pwm0_duty(intAdjust+57+intSpeed); // Phase U PWM Duty Setting
set_power_pwm2_duty(intAdjust+14+intSpeed/6); // Phase V PWM Duty Setting
set_power_pwm4_duty(intAdjust+14+intSpeed/6); // Phase W PWM Duty Setting
intCounter++;
if (intCounter > 1799) {
set_adc_channel(0); // Select ADC Channel 0
delay_us(10);
intFBFinal = read_adc(); // Read Feedback from ADC
delay_us(10);
intAdjust = intFBInital - intFBFinal; // Calculate Speed Adjust
intCounter = 0;
}
}
}
|
On the updated datasheet I provided it's table 21-3 on page 251. Note 3 says:
Quote: | For device frequencies above 1 MHz, the device must be in Sleep for the entire conversion or the A/D accuracy may be out of specification unless in Single-Shot mode. |
Does that mean I have to put the chip in some kind of low powered sleep mode before I can gather a proper reading or something? Because right now, changing the clock speed doesn't seem to show any difference on the scope. Also here is the output to my screen...
Quote: |
Start Test
Interrupt 1. Per= 13, S= 44, Analog= 89
Interrupt 2. Per= 13, S= 44, Analog= 89
Interrupt 3. Per= 10, S= 14, Analog= 29
Interrupt 4. Per= 10, S= 14, Analog= 29
Interrupt 5. Per= 60, S= -2, Analog= -3
Interrupt 6. Per= 60, S= -1, Analog= -1
Interrupt 7. Per= 20, S= 112, Analog= -31
Interrupt 8. Per= 20, S= 113, Analog= -29
Interrupt 9. Per= 20, S= 112, Analog= -31
Interrupt 10. Per= 20, S= 112, Analog= -31
Interrupt 11. Per= 11, S= 25, Analog= 51
Interrupt 12. Per= 11, S= 25, Analog= 51
|
So at least I got the interrupts to work, but I don't like how it jams up the wave form |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19520
|
|
Posted: Mon Feb 25, 2013 1:31 am |
|
|
No.
The note only applies to the clocks with the notes against them the internal RC, and the internal RC/4.
You can use these oscillators, but only if you put the chip to sleep, which would stop your PWM. Hence not suitable for you.
That is the reason to change to the master oscillator derived clocks which don't have this note.
However ADC_CLOCK_DIV_2, is not legal at your clock rate. Look along the lines in the table 2Tosc (ADC_CLOCK_DIV_2), is legal for a maximum clock rate of 4.8MHz. At your 8MHz rate, you need to use DIV_4. You are clocking the ADC faster than it supports.
You need to actually read what the sheet says.
Best Wishes |
|
|
|
|
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
|