Not simple BLDC controller It RUNS! :)

Awesome thanks. It feels good to learn a little every day, I have felt like this before in my life and from that experiance I know its only a matter of time till I realy get it!
 
Arlo, this one compiles at least!
Code:
// Arlo, this may not be correct, but it does now compile.  I do not have your
// hardware configuration to make things right, and of course, every author does
// things differently.  So to rethink to this approach, especially takes more time
// than I have right now, to make the ADC stuff right.  The dsPIC has a very complicated
// ADC with many ways to control the sampling.  You just have to study it for hours.
// Like others said, make small steps, and MAKE SURE you understand what you did.
// This wil be a long journey!  Good luck!
#define  __p30F3010__
#include  "p30F3010.h"								// put compiler dsPIC.h file in root
#include  "adc10.h"
#include  "delay.h"
//-----------------------------------------------------------------------------
//Configuration bits
_FOSC(CSW_FSCM_OFF & XT_PLL4);
_FWDT(WDT_OFF);
_FBORPOR (PBOR_OFF & PWRT_16 & MCLR_EN);
_FGS(CODE_PROT_OFF);
//-----------------------------------------------------------------------------
//Program Specific Constants
// Arlo, I need to know your crystal frequency to get this part right
#define FCY 				7372800 					//Instruction cycle rate (Osc x PLL / 4)
#define MILLISEC 		FCY/10000					// 1 mSec delay constant

// subroutines or functions must be defined before they are used ===============
void DelayNmSec(unsigned int N){
	unsigned int j;
	while(N--)
 	for(j=0;j < MILLISEC;j++);
}

// ADC_Init() ==================================================================
// this ADC is VERY complicated Arlo, this took me two days to figure out originally
// I am not sure this is right because I do not know your hardware configuration
// Study dsPIC30F3010-2011-70141e.pdf file from Microchip Pages 127 to 138
// Study DSPic30F_Family_ReferenceManual_70046E.pdf file from Microchip pages 401 to 460

void ADC_Init(void) {									// functions must be defined before you use them 
	ADPCFG = 0xFFFB;    								// all PORTB = Digital; RB2 = analog
	ADCON1 	= 0x00E4; 									// Autoconvert starts conversion, auto sampling
	ADCON2 = 0;													// sample CH0 channel only
	ADCHS = 0x0002;     								// Connect RB2/AN2 as CH0 input in this example RB2/AN2 is the input
	ADCON3 	= 0x0080; 									// Tad = internal RC clock (4uS)
		
	ADCSSL = 0;										// not sure on this register, I will need to research it's effects
	
	IFS0bits.ADIF 	= 0; 								// clear ADC interrupt flag
	ADCON1bits.ADON = 1; 								// turn ADC ON
	}

// main routine ================================================================
int main(void) {
unsigned int ADCValue;

	// Arlo, I assume your LED is on Pin D0
	LATD 	= 0xfffe;        							// Writes to the latch, sets DO to off state for LED
	TRISD = 0xfffe;       							// O sets pin as output for driving LED on DO
	
// This should flash your LED 5 times at startup
int ijk;
for (ijk = 0; ijk < 5; ijk++) {
	PORTDbits.RD0 = 1;									// turn on D0 for LED
	DelayNmSec(500);										// delay a half second
	PORTDbits.RD0 = 0;									// turn off DO
	DelayNmSec(500);										// delay a half second
	}																		// end of for

// now lets play with the adc
	ADC_Init();              						// call Initialize ADC to initialize it
	

while (1)  {
	ADCON1bits.SAMP = 1; 								// sampling begins immediately after last conversion
	DelayNmSec(100);     // for 100 mS
	
	while (!ADCON1bits.DONE);   				// conversion done?
		ADCValue = ADCBUF0;    						// yes Now ADCValue holds the value for you to use
	}																		// end of the while(1) loop	

}																			// end of main
 
bigmoose said:
Arlo, this one compiles at least!
5Mhz Thanks so much. I just realized today this could be set as a pour mans Brushed motor controller. I have to think about that I might build something to help the drag race hi out with the s10 build... A brushed controller will be a walk in the park after this.
 
Based on the 5MHz crystal, this part of the code should change:
Code:
//Program Specific Constants
//Fcy = cycle clock = Fosc/4 = (XTAL * PLLmultiplier)/(4*PostScaler)
#define FCY 				5000000 					// 5 MHz Xtal*PLLof4/(4*Postscalerof1)
#define MILLISEC 		FCY/10000					// 1 mSec delay constant
 
Thanks for the awesome note BigM thats so nice of you. It compiles for me so now tomorow after work I will build up some more of my board and test this!
 
So I found with some searching
//ADCSSL: A/D Input Scan Select Register
ADCSSL = 0; //clear register
Ill keep digging as well I will try to figure out how to use the ADC value for a timed pulse.
 
Here is another list of AP notes.
Using the Analog-to-Digital (A/D) Converter AN546
Four Channel Digital Voltmeter with Display and Keyboard AN557
Understanding A/D Converter Performance Specifications AN693
Using the dsPIC30F for Sensorless BLDC Control AN901
Using the dsPIC30F for Vector Control of an ACIM AN908
Sensored BLDC Motor Control Using the dsPIC30F2010 AN957
An Introduction to AC Induction Motor Control Using the dsPIC30F MCU AN984
 
Arlo, you're still focused at the "control LED flash speed with throttle" program, right? Do you intent to follow my suggested algorithm?

1) Read the throttle position (ADC)
2) Transform the throttle position into a time delay value
3) Wait for the amount of time calculated in 2) (this will be half the time period or your flashing LED)
4) Light up your LED (port perform I/O, setting a bit)
5) Do another delay as in 3)
6) Turn off your LED
7) Go back to 1) to repeat it all over again

If so, it's time to copy the steps above into comments in your program as Lebowski suggests, that will help you a lot to get this through. In the last code posted by BigM you already have an almost complete set of steps to read an ADC

Code:
   ADCON1bits.SAMP = 1;                         // sampling begins immediately after last conversion
   DelayNmSec(100);     // for 100 mS

   while (!ADCON1bits.DONE);               // conversion done?
      ADCValue = ADCBUF0;                      // yes Now ADCValue holds the value for you to use
   }                                                      // end of the while(1) loop
I suggest you to put group ADC reading steps inside a function, returning the value read from the ADC. This will make it much easier to handle complexity (once you have all the steps grouped and "hidden" inside a function, you just need to remember the function's name and you don't care about the ADC reading details anymore) and to re-use code (then you'll just have to call the function to read the ADC, instead of writing all of the steps over and over). A C function is declared by giving it a return type, a name, an argument list (which can be empty) and a body (code enclosed in {}); inside the body use "return XXX;" to return back from the function with value XXX (which is a constant value like 5096 or a variable or register like ADCBUF0). An example of a function that return nothing ("void" means roughly "nothing") and has no arguments is ADC_init, you can start from there. Another example of a function is main, which takes no arguments but returns an 'int' type value. The function you should to to read the ADC should return a value of the int type also - 'int' means an integer number .Take a quick look at the function's chapter of a C book or some reference in the Internet.

Having your function to read and return an ADC value, you just need to call it by name from your code storing it into a variable for later usage, and step 1) of the algorithm is done.
 
Njay said:
Arlo, you're still focused at the "control LED flash speed with throttle" program, right? Do you intent to follow my suggested algorithm?

1) Read the throttle position (ADC)
2) Transform the throttle position into a time delay value
3) Wait for the amount of time calculated in 2) (this will be half the time period or your flashing LED)
4) Light up your LED (port perform I/O, setting a bit)
5) Do another delay as in 3)
6) Turn off your LED
7) Go back to 1) to repeat it all over again

If so, it's time to copy the steps above into comments in your program as Lebowski suggests, that will help you a lot to get this through. In the last code posted by BigM you already have an almost complete set of steps to read an ADC
Yeh Im working on this all day today. And every evening this week. Then Im off from the 25-the3rd so Ill be working on it then too.
I took note of your list of steps and have been kinda working on them then trying to compile as I go to see if it works.
I will try to get the last step today.
 
Arlo, one of the first things I like to get functional is some type of serial communications with the board. I may have misled some by labeling my interface 5V RS232 because the official spec requires +-12V usually with a MAX232 chip to the PC. I usually put the MAX232 or a USB chip in the cable connector and only take the 5V signals off board. Not right, not wrong, just my "style".

That said, the serial link to a PC gives you the ability for the micro board under development to "talk to you" and spew out diagnostics. When I first tried to get the PWM generator and ADC working it did take me days... lots of "stupid" errors... but it is how it is. When you finally get it all working, it is then "obvious" ... until you go back to it in a year!

The serial link can spew out variables and you can look for change and patterns. I use it, and if you look at Lebowski's posts, he spews a lot of serial data out also during development. It gives incredible insight into what the chip is really doing, versus what you think it should be doing.

If you were to see any of my production code examples you would see it loaded with all the serial output diagnostics that are turned on and off by compiler directives. I like to leave the diagnostic code in the final source for when I go back to steal some of it for another project. Here is an example:
Code:
#ifdef debug
	i=1;
	printf("***%4u ThrottleLI %6ld  PDC2 %6u PTPERloadLU %6lu SEVTCMP %6u\n\r",
         ADCcount, ThrottleLI, PDC2, PTPERloadLU, SEVTCMP);
#endif
 
Njay this is what the code looks like so far.
Code:
// Arlo, this may not be correct, but it does now compile.  I do not have your
// hardware configuration to make things right, and of course, every author does
// things differently.  So to rethink to this approach, especially takes more time
// than I have right now, to make the ADC stuff right.  The dsPIC has a very complicated
// ADC with many ways to control the sampling.  You just have to study it for hours.
// Like others said, make small steps, and MAKE SURE you understand what you did.
// This wil be a long journey!  Good luck!
#define  __p30F3010__
#include  "p30F3010.h"                        // put compiler dsPIC.h file in root
#include  "adc10.h"
#include  "delay.h"
//-----------------------------------------------------------------------------
//Configuration bits
_FOSC(CSW_FSCM_OFF & XT_PLL4);
_FWDT(WDT_OFF);
_FBORPOR (PBOR_OFF & PWRT_16 & MCLR_EN);
_FGS(CODE_PROT_OFF);
//-----------------------------------------------------------------------------
//Program Specific Constants
//Fcy = cycle clock = Fosc/4 = (XTAL * PLLmultiplier)/(4*PostScaler)
#define FCY             5000000                // 5 MHz Xtal*PLLof4/(4*Postscalerof1)
#define MILLISEC       FCY/10000               // 1 mSec delay constant
// subroutines or functions must be defined before they are used ===============
void DelayNmSec(unsigned int N){
   unsigned int j;
   while(N--)
    for(j=0;j < MILLISEC;j++);
}

// ADC_Init() ==================================================================
// this ADC is VERY complicated Arlo, this took me two days to figure out originally
// I am not sure this is right because I do not know your hardware configuration
// Study dsPIC30F3010-2011-70141e.pdf file from Microchip Pages 127 to 138
// Study DSPic30F_Family_ReferenceManual_70046E.pdf file from Microchip pages 401 to 460

void ADC_Init(void) {                           // functions must be defined before you use them 
   ADPCFG = 0xFFFB;                            // all PORTB = Digital; RB2 = analog
   ADCON1    = 0x00E4;                            // Autoconvert starts conversion, auto sampling
   ADCON2 = 0;                                       // sample CH0 channel only
   ADCHS = 0x0002;                  // Connect RB2/AN2 as CH0 input in this example RB2/AN2 is the input
   ADCON3    = 0x0080;                            // Tad = internal RC clock (4uS)
      
   ADCSSL = 0;                        // not sure on this register, I will need to research it's effects
   
   IFS0bits.ADIF    = 0;                         // clear ADC interrupt flag
   ADCON1bits.ADON = 1;                         // turn ADC ON
   }

// main routine ================================================================
int main(void) {
unsigned int ADCValue;

   // Arlo, I assume your LED is on Pin D0
   LATD    = 0xfffe;                             // Writes to the latch, sets DO to off state for LED
   TRISD = 0xfffe;                            // O sets pin as output for driving LED on DO
   
// This should flash your LED 5 times at startup
int ijk;
for (ijk = 0; ijk < 5; ijk++) {
   PORTDbits.RD0 = 1;                           // turn on D0 for LED
   DelayNmSec(500);                              // delay a half second
   PORTDbits.RD0 = 0;                           // turn off DO
   DelayNmSec(500);                              // delay a half second
   }                                                      // end of for

// now lets play with the adc
   ADC_Init();                                // call Initialize ADC to initialize it
   

while (1)  {
   ADCON1bits.SAMP = 1;                         // sampling begins immediately after last conversion
   DelayNmSec(100);     // for 100 mS
   
   while (!ADCON1bits.DONE);               // conversion done?
      ADCValue = ADCBUF0;                      // yes Now ADCValue holds the value for you to use
   }                                                      // end of the while(1) loop   

}                                                         // end of main
As you can see the ADC is in a function. Now I just need to figure out how to use the result of that function to make a PWM for the led.
 
No Arlo, what you have in a function (ADC_Init()) is just the initialization of the ADC (hw module). The code that really takes an ADC reading is composed of the few steps I copied into my post, and those are not inside a function (of its own), they are just inside the main infinite loop (while (1) { ... }). If you move those steps to the inside of a function, you'll be able to execute them in the main infinite loop by just calling the function's name and saving the returned value in a variable to use later, like

ADCValue = ReadADC();

assuming you name the function "ReadADC".
 
Njay said:
No Arlo, what you have in a function (ADC_Init()) is just the initialization of the ADC (hw module). The code that really takes an ADC reading is composed of the few steps I copied into my post, and those are not inside a function (of its own), they are just inside the main infinite loop (while (1) { ... }). If you move those steps to the inside of a function, you'll be able to execute them in the main infinite loop by just calling the function's name and saving the returned value in a variable to use later, like

ADCValue = ReadADC();

assuming you name the function "ReadADC".
Ok Njay like this?

Code:
// Arlo, this may not be correct, but it does now compile.  I do not have your
// hardware configuration to make things right, and of course, every author does
// things differently.  So to rethink to this approach, especially takes more time
// than I have right now, to make the ADC stuff right.  The dsPIC has a very complicated
// ADC with many ways to control the sampling.  You just have to study it for hours.
// Like others said, make small steps, and MAKE SURE you understand what you did.
// This wil be a long journey!  Good luck!
#define  __p30F3010__
#include  "p30F3010.h"                        // put compiler dsPIC.h file in root
#include  "adc10.h"
#include  "delay.h"
//-----------------------------------------------------------------------------
//Configuration bits
_FOSC(CSW_FSCM_OFF & XT_PLL4);
_FWDT(WDT_OFF);
_FBORPOR (PBOR_OFF & PWRT_16 & MCLR_EN);
_FGS(CODE_PROT_OFF);
//-----------------------------------------------------------------------------
//Program Specific Constants
//Fcy = cycle clock = Fosc/4 = (XTAL * PLLmultiplier)/(4*PostScaler)
#define FCY             5000000                // 5 MHz Xtal*PLLof4/(4*Postscalerof1)
#define MILLISEC       FCY/10000               // 1 mSec delay constant
// subroutines or functions must be defined before they are used ===============
void DelayNmSec(unsigned int N){
   unsigned int j;
   while(N--)
    for(j=0;j < MILLISEC;j++);
}

// ADC_Init() ==================================================================
// this ADC is VERY complicated Arlo, this took me two days to figure out originally
// I am not sure this is right because I do not know your hardware configuration
// Study dsPIC30F3010-2011-70141e.pdf file from Microchip Pages 127 to 138
// Study DSPic30F_Family_ReferenceManual_70046E.pdf file from Microchip pages 401 to 460

void ADC_Init(void) {                           // functions must be defined before you use them 
   ADPCFG = 0xFFFB;                            // all PORTB = Digital; RB2 = analog
   ADCON1    = 0x00E4;                            // Autoconvert starts conversion, auto sampling
   ADCON2 = 0;                                       // sample CH0 channel only
   ADCHS = 0x0002;                  // Connect RB2/AN2 as CH0 input in this example RB2/AN2 is the input
   ADCON3    = 0x0080;                            // Tad = internal RC clock (4uS)
      
   ADCSSL = 0;                        // not sure on this register, I will need to research it's effects
   
   IFS0bits.ADIF    = 0;                         // clear ADC interrupt flag
   ADCON1bits.ADON = 1;                         // turn ADC ON
   }
   // ReadADC function=====================================================
 int ReadADC () {
   ADCON1bits.SAMP = 1;                         // sampling begins immediately after last conversion
   DelayNmSec(100);     // for 100 mS
   
   while (!ADCON1bits.DONE);               // conversion done?
      ADCValue = ADCBUF0;                      // yes Now ADCValue holds the value for you to use
       }

// main routine ================================================================
int main(void) {
unsigned int ADCValue;

   // Arlo, I assume your LED is on Pin D0
   LATD    = 0xfffe;                             // Writes to the latch, sets DO to off state for LED
   TRISD = 0xfffe;                            // O sets pin as output for driving LED on DO
   
// This should flash your LED 5 times at startup
int ijk;
for (ijk = 0; ijk < 5; ijk++) {
   PORTDbits.RD0 = 1;                           // turn on D0 for LED
   DelayNmSec(500);                              // delay a half second
   PORTDbits.RD0 = 0;                           // turn off DO
   DelayNmSec(500);                              // delay a half second
   }                                                      // end of for

// now lets play with the adc
   ADC_Init();                                // call Initialize ADC to initialize it
   

while (1)  {
ADCValue = ReadADC();                            // ReadADC = value of ADC
   }                                               // end of the while(1) loop   

}                                                    // end of main
 
Sorry Njay I just went back and re-read all the posts by you and Lebowski and found what he said about writing the steps first. This does make sense.
I have not been about to quite get what you want me to do in the last posts. I think I understand you are saying you make a function and give it a name so you just need to call the name later on. But I cant get anything to compile.
 
Arlo, I have a folder for you on my compiler, so post in the code section exactly what you have and I'll find why it will not compile and post the solution for you.
 
bigmoose said:
Arlo, I have a folder for you on my compiler, so post in the code section exactly what you have and I'll find why it will not compile and post the solution for you.
Thanks Bigmoose. I posted what I was trying 2 posts ago. Im going back over it now. Its a matter of understanding C programing better and understanding what Njay is saying. I got called for some work at my shop so I went and cleaned and organized while I waited for 2 no shows :? I Realy need to lock my self in a room with some soothing music to get down to this.

One other question how do I build a new c file from scratch???
 
That's it Arlo, you're getting there. The function you created is (I indented it a bit for improved reading)

Code:
// ReadADC function=====================================================
int ReadADC ()
{
    ADCON1bits.SAMP = 1;             // sampling begins immediately after last conversion
    DelayNmSec(100);                   // wait for 100 mS
   
    while (!ADCON1bits.DONE);      // conversion done?
    ADCValue = ADCBUF0;             // yes Now ADCValue holds the value for you to use
}
Now there are some problems here. The 1st one is that you are not telling it what value to return. Remember my post back about how to return values from functions?
The second is that you are using a variable (ADCValue) without having it declared 1st. Variable declarations are only valid inside the block (a C "block" is code inside {}) where they are declared. The one declared in your main() function, although it is the same name, is in a different block and therefore it's an entirelly different variable that is only "visible" inside that block.
One other thing you'll want to change is the function's return type. I know I told you type 'int' but I didn't notice the ADC values are 'unsigned int', sorry about that. 'unsigned' removes all of the negative numbers from being able to be represented in the variable or function return type (and increase the maximum representable number).
 
I'm starting to wonder if Assmebly with it's limitted instruction set wouldn't be easier ? Though that will have penalties when it comes to math though.

Anyway (don't want to start that discussion again), I see you assign values to an output
pin on D by using 'PORTD'. Because of the speed of these devices it's better to write to
a pin on D using 'LATD' and to read from a pin using 'PORTD'. (see datasheet)
 
Lebowski said:
I'm starting to wonder if Assmebly with it's limitted instruction set wouldn't be easier ? Though that will have penalties when it comes to math though.

Anyway (don't want to start that discussion again), I see you assign values to an output
pin on D by using 'PORTD'. Because of the speed of these devices it's better to write to
a pin on D using 'LATD' and to read from a pin using 'PORTD'. (see datasheet)
For one I have been looking to learn C for a while. I will get it not to worry.
For two I am just practicing with the controller. I will assign the proper pin next that's easy or at least I have a basic understanding.
I really really have not got the time I wanted to work on this... The usual life shit is in my way but.... Its what pays the bills etc. As I get more organized I will speed up my production. Its a slow start for me but hard with little direction and your guys help is very appreciated.
 
OK so its my understanding I want to return a variable In the ADCvalue function. How do I do this? Or make me work for it so I learn where do I read up on this? :mrgreen:
 
Probably want to read a "C" programming primer.

Something like:

Code:
function readADC()
{
    int value;
    //...
    value = 0;       // read hardware here
    return value;  // return value
}

void main()
{
    //...
    a = readADC();
    //...
}

Start simple, work gradually up. But study the language constructs. Probably should do that before getting into the micro stuff. Find a simple "learn C" tutorial and go through it. Get a good book and put plenty of post-its in appropriate places, review it frequently as you use the constructs.
 
Ok so I worked on it a bit tonight.
Here is where I am at. I will work on it again tomorrow for a bit. Snow Day? Crossing fingers!
Found another good place to read up on C programing. http://www.vectorsite.net/tscpp.html

Code:
// Arlo, this may not be correct, but it does now compile.  I do not have your
// hardware configuration to make things right, and of course, every author does
// things differently.  So to rethink to this approach, especially takes more time
// than I have right now, to make the ADC stuff right.  The dsPIC has a very complicated
// ADC with many ways to control the sampling.  You just have to study it for hours.
// Like others said, make small steps, and MAKE SURE you understand what you did.
// This wil be a long journey!  Good luck!
#define  __p30F3010__
#include  "p30F3010.h"                        // put compiler dsPIC.h file in root
#include  "adc10.h"
#include  "delay.h"
//-----------------------------------------------------------------------------
//Configuration bits
_FOSC(CSW_FSCM_OFF & XT_PLL4);
_FWDT(WDT_OFF);
_FBORPOR (PBOR_OFF & PWRT_16 & MCLR_EN);
_FGS(CODE_PROT_OFF);
//-----------------------------------------------------------------------------
//Program Specific Constants
//Fcy = cycle clock = Fosc/4 = (XTAL * PLLmultiplier)/(4*PostScaler)
#define FCY             5000000                // 5 MHz Xtal*PLLof4/(4*Postscalerof1)
#define MILLISEC       FCY/10000               // 1 mSec delay constant
// subroutines or functions must be defined before they are used ===============
void DelayNmSec(unsigned int N){
   unsigned int j;
   while(N--)
    for(j=0;j < MILLISEC;j++);
}

// ADC_Init() ==================================================================
// this ADC is VERY complicated Arlo, this took me two days to figure out originally
// I am not sure this is right because I do not know your hardware configuration
// Study dsPIC30F3010-2011-70141e.pdf file from Microchip Pages 127 to 138
// Study DSPic30F_Family_ReferenceManual_70046E.pdf file from Microchip pages 401 to 460

void ADC_Init(void) {                           // functions must be defined before you use them 
   ADPCFG = 0xFFFB;                            // all PORTB = Digital; RB2 = analog
   ADCON1    = 0x00E4;                            // Autoconvert starts conversion, auto sampling
   ADCON2 = 0;                                       // sample CH0 channel only
   ADCHS = 0x0002;                  // Connect RB2/AN2 as CH0 input in this example RB2/AN2 is the input
   ADCON3    = 0x0080;                            // Tad = internal RC clock (4uS)
      
   ADCSSL = 0;                        // not sure on this register, I will need to research it's effects
   
   IFS0bits.ADIF    = 0;                         // clear ADC interrupt flag
   ADCON1bits.ADON = 1;                         // turn ADC ON
   }
   // ReadADC function=====================================================
unsigned int ReadADC () {
   ADCON1bits.SAMP = 1;                         // sampling begins immediately after last conversion
   DelayNmSec(100);     // for 100 mS
   
   while (!ADCON1bits.DONE);               // conversion done?
      ADCValue = ADCBUF0;                      // yes Now ADCValue holds the value for you to use
   return ADCvalue;                            //Value of ADC
       }

// main routine ================================================================
int main(void) {
unsigned int ADCValue;
   // Arlo, I assume your LED is on Pin D0
   LATD    = 0xfffe;                             // Writes to the latch, sets DO to off state for LED
   TRISD = 0xfffe;                            // O sets pin as output for driving LED on DO
   
// This should flash your LED 5 times at startup
int ijk;
for (ijk = 0; ijk < 5; ijk++) {
   PORTDbits.RD0 = 1;                           // turn on D0 for LED
   DelayNmSec(500);                              // delay a half second
   PORTDbits.RD0 = 0;                           // turn off DO
   DelayNmSec(500);                              // delay a half second
   }                                                      // end of for

// now lets play with the adc
   ADC_Init();                                // call Initialize ADC to initialize it
   

while (1)  {
  // Take an ADC conversion and use it to set Timer0
        TMR0H = ADC_Convert();      // MSB from ADC
        TMR0L = 0;                  // LSB = 0
   } 
     //Timer scale function
void Timer0_Init(void)
{
    INTCONbits.TMR0IF = 0;          // clear roll-over interrupt flag
    T0CON = 0b00000001;             // prescale 1:4 - about 1 second maximum delay.
    TMR0H = 0;                      // clear timer - always write upper byte first
    TMR0L = 0;
    T0CONbits.TMR0ON = 1;           // start timer
}
                                              // end of the while(1) loop   

}                                                    // end of main
 
Ok so I put "unsigned int ADCvalue" (unsigned int for whole positive numbers) before the curley bracket in my ReadADC function and now Im just down to two syntax errors. Is this right???

Code:
// Arlo, this may not be correct, but it does now compile.  I do not have your
// hardware configuration to make things right, and of course, every author does
// things differently.  So to rethink to this approach, especially takes more time
// than I have right now, to make the ADC stuff right.  The dsPIC has a very complicated
// ADC with many ways to control the sampling.  You just have to study it for hours.
// Like others said, make small steps, and MAKE SURE you understand what you did.
// This wil be a long journey!  Good luck!
#define  __p30F3010__
#include  "p30F3010.h"                        // put compiler dsPIC.h file in root
#include  "adc10.h"
#include  "delay.h"
//-----------------------------------------------------------------------------
//Configuration bits
_FOSC(CSW_FSCM_OFF & XT_PLL4);
_FWDT(WDT_OFF);
_FBORPOR (PBOR_OFF & PWRT_16 & MCLR_EN);
_FGS(CODE_PROT_OFF);
//-----------------------------------------------------------------------------
//Program Specific Constants
//Fcy = cycle clock = Fosc/4 = (XTAL * PLLmultiplier)/(4*PostScaler)
#define FCY             5000000                // 5 MHz Xtal*PLLof4/(4*Postscalerof1)
#define MILLISEC       FCY/10000               // 1 mSec delay constant
// subroutines or functions must be defined before they are used ===============
void DelayNmSec(unsigned int N){
   unsigned int j;
   while(N--)
    for(j=0;j < MILLISEC;j++);
}

// ADC_Init() ==================================================================
// this ADC is VERY complicated Arlo, this took me two days to figure out originally
// I am not sure this is right because I do not know your hardware configuration
// Study dsPIC30F3010-2011-70141e.pdf file from Microchip Pages 127 to 138
// Study DSPic30F_Family_ReferenceManual_70046E.pdf file from Microchip pages 401 to 460

void ADC_Init(void) {                           // functions must be defined before you use them 
   ADPCFG = 0xFFFB;                            // all PORTB = Digital; RB2 = analog
   ADCON1    = 0x00E4;                            // Autoconvert starts conversion, auto sampling
   ADCON2 = 0;                                       // sample CH0 channel only
   ADCHS = 0x0002;                  // Connect RB2/AN2 as CH0 input in this example RB2/AN2 is the input
   ADCON3    = 0x0080;                            // Tad = internal RC clock (4uS)
      
   ADCSSL = 0;                        // not sure on this register, I will need to research it's effects
   
   IFS0bits.ADIF    = 0;                         // clear ADC interrupt flag
   ADCON1bits.ADON = 1;                         // turn ADC ON
   }
   // ReadADC function=====================================================
unsigned int ReadADC ()
unsigned int ADCvalue
   {
   ADCON1bits.SAMP = 1;                         // sampling begins immediately after last conversion
   DelayNmSec(100);     // for 100 mS
   
   while (!ADCON1bits.DONE);               // conversion done?
      ADCValue = ADCBUF0;                      // yes Now ADCValue holds the value for you to use
   return ADCvalue;                            //Value of ADC
       }

// main routine ================================================================
int main(void) {
unsigned int ADCValue;
              // Arlo, I assume your LED is on Pin D0
   LATD    = 0xfffe;                             // Writes to the latch, sets DO to off state for LED
   TRISD = 0xfffe;                            // O sets pin as output for driving LED on DO
   
           // This should flash your LED 5 times at startup
int ijk;                           // From bigmoose
for (ijk = 0; ijk < 5; ijk++) {
   PORTDbits.RD0 = 1;                           // turn on D0 for LED
   DelayNmSec(500);                              // delay a half second
   PORTDbits.RD0 = 0;                           // turn off DO
   DelayNmSec(500);                              // delay a half second
   }                                                      // end of for

// now lets play with the adc
   ADC_Init();                                // call Initialize ADC to initialize it
   

while (1)  {
  // Take an ADC conversion and use it to set Timer0
        TMR0H = ADC_Convert();      // MSB from ADC
        TMR0L = 0;                  // LSB = 0
   } 
     //Timer scale function
void Timer0_Init(void)
{
    INTCONbits.TMR0IF = 0;          // clear roll-over interrupt flag
    T0CON = 0b00000001;             // prescale 1:4 - about 1 second maximum delay.
    TMR0H = 0;                      // clear timer - always write upper byte first
    TMR0L = 0;
    T0CONbits.TMR0ON = 1;           // start timer
}
                                              // end of the while(1) loop   

}                                                    // end of main

With that I get
----------------------------------------------------------------------
Release build of project `C:\Program Files (x86)\Microchip\Tps Led.mcp' started.
Language tool versions: pic30-as.exe v3.30, pic30-gcc.exe v3.30, pic30-ld.exe v3.30, pic30-ar.exe v3.30
Wed Dec 21 07:33:23 2011
----------------------------------------------------------------------
Clean: Deleting intermediary and output files.
Clean: Done.
Executing: "C:\Program Files (x86)\Microchip\mplabc30\v3.30c\bin\pic30-gcc.exe" -mcpu=30F3010 -x c -c "Arlo1.c" -o"Arlo1.o" -g -Wall
Arlo1.c: In function 'ReadADC':
Arlo1.c:51: error: syntax error before '{' token
Arlo1.c:69: error: syntax error before 'for'
Halting build on first failure as requested.
----------------------------------------------------------------------
Release build of project `C:\Program Files (x86)\Microchip\Tps Led.mcp' failed.
Language tool versions: pic30-as.exe v3.30, pic30-gcc.exe v3.30, pic30-ld.exe v3.30, pic30-ar.exe v3.30
Wed Dec 21 07:33:23 2011
----------------------------------------------------------------------
BUILD FAILED
 
Arlo, you have more reading to do... this is tough, I know. Note that ADCValue is a different variable than ADCvalue. Case matters to the compiler.

Next, you cannot cut and paste PIC code between chips. For example the dsPIC30F does not have a timer 0, yet you used pointers to it. That won't work and won't compile for a reason.

Brackets matter. Mind what you are bracketing.

This still won't compile because of the timer issues. I would like you to work on fixing it, so that you can learn. I would recommend smaller steps in learning.

Keep trying though.

Code:
#define  __p30F3010__
#include  "p30F3010.h"                 // put compiler dsPIC.h file in root
#include  "adc10.h"
#include  "delay.h"
//-----------------------------------------------------------------------------
//Configuration bits
_FOSC(CSW_FSCM_OFF & XT_PLL4);
_FWDT(WDT_OFF);
_FBORPOR (PBOR_OFF & PWRT_16 & MCLR_EN);
_FGS(CODE_PROT_OFF);
//-----------------------------------------------------------------------------
//Program Specific Constants
//Fcy = cycle clock = Fosc/4 = (XTAL * PLLmultiplier)/(4*PostScaler)
#define FCY             5000000        // 5 MHz Xtal*PLLof4/(4*Postscalerof1)
#define MILLISEC       FCY/10000       // 1 mSec delay constant


// Put global variables here
unsigned int ADCValue;  

// subroutines or functions must be defined before they are used ===============
// subroutines or functions must be defined before they are used ===============
// subroutines or functions must be defined before they are used ===============
// subroutines or functions must be defined before they are used ===============

// void DelayNmSec(unsigned int N) =============================================
void DelayNmSec(unsigned int N){
   unsigned int j;
   while(N--)
    for(j=0;j < MILLISEC;j++);
   }

// void ADC_Init() ==================================================================
void ADC_Init(void) {                  // functions must be defined before you use them 
   ADPCFG = 0xFFFB;                    // all PORTB = Digital; RB2 = analog
   ADCON1 = 0x00E4;                    // Autoconvert starts conversion, auto sampling
   ADCON2 = 0;                         // sample CH0 channel only
   ADCHS  = 0x0002;                    // Connect RB2/AN2 as CH0 input in this example RB2/AN2 is the input
   ADCON3 = 0x0080;                    // Tad = internal RC clock (4uS)
      
   ADCSSL = 0;                         // not sure on this register, I will need to research it's effects
   
   IFS0bits.ADIF    = 0;               // clear ADC interrupt flag
   ADCON1bits.ADON = 1;                // turn ADC ON
   }

// ReadADC function =====================================================
unsigned int ReadADC(void){
   ADCON1bits.SAMP = 1;                // sampling begins immediately after last conversion
   DelayNmSec(100);                    // for 100 mS
   
   while (!ADCON1bits.DONE);           // conversion done?
      ADCValue = ADCBUF0;              // yes Now ADCValue holds the value for you to use
   return ADCValue;                    // Value of ADC
   }

// void Timer0_Init(void) ===============================================
/* ARLO, where did you get this code from?  You cannot cut and paste code from different "families"
of PIC's dsPIC's etc. THEY ARE ALL DIFFERENT!  dsPIC30F3010 does not have a timer 0!  So none of this
would ever work!
*/
void Timer0_Init(void)
	{
    INTCONbits.TMR0IF = 0;             // clear roll-over interrupt flag
    T0CON = 0b00000001;                // prescale 1:4 - about 1 second maximum delay.
    TMR0H = 0;                         // clear timer - always write upper byte first
    TMR0L = 0;
    T0CONbits.TMR0ON = 1;              // start timer
	}

// main routine ================================================================
int main(void) {
              // Arlo, I assume your LED is on Pin D0
   LATD    = 0xfffe;                   // Writes to the latch, sets DO to off state for LED
   TRISD = 0xfffe;                     // O sets pin as output for driving LED on DO
   
           // This should flash your LED 5 times at startup
int ijk;                           // From bigmoose
for (ijk = 0; ijk < 5; ijk++) {
   PORTDbits.RD0 = 1;                  // turn on D0 for LED
   DelayNmSec(500);                    // delay a half second
   PORTDbits.RD0 = 0;                  // turn off DO
   DelayNmSec(500);                    // delay a half second
   }                                                      // end of for

// now lets play with the adc
   ADC_Init();                         // call Initialize ADC to initialize it
   

while (1)  {
  // Take an ADC conversion and use it to set Timer0
//ARLO ADC_Convert(0) is another function that you did not define...
        TMR0H = ADC_Convert();         // MSB from ADC
        TMR0L = 0;                     // LSB = 0
    
     //Timer scale function

 }                                     // end of the while(1) loop   

}                                      // end of main
 
Back
Top