Hi All,
Thanks to Hugh and Kent for the regular help on this forum, I have been able to use GCBasic to make some decent working timing circuits for my control-line model planes with electric motors. The electronic speed controllers (esc's) normally require a 1 to 2 ms signal from an R/C receiver, but we don't use any R/C stuff on control-line, so we need a timer to set the flight time and also the motor speed.
I've managed to program PIC 12F675 chips that work very well and do almost all of my needs........but....(and there is always a "but") I now need to compensate for the battery voltage dropping over the flight time by reading the value from one of the AN ports. You can in fact buy esc's with a governor mode that keeps the motor speed constant, but I would like to try this another way.
O.K Here's the problem. I wrote a simple routine to run the servo by reading the AN(0) port, and then using the result to run a servo backwards and forwards. I use a servo because it's easier that going to my workshop and hooking up a scope. The pot is on the Pickit2 proto board, and if I stay in the centre range of the pot, the servo works o.k. To see what the voltage is read as, I write the value to the first eeprom memory, and then read it with the Pickit software. For a voltage range of 0 to 3.8 volts, I get 0 to 0C Hex. The numbers to run the servo are 100 to 200 with are multiplied by 10 us.
So...what on earth am I putting into the eeprom? The servo works between the 2 extremes, so why can't I store this value as is? Is this a Low/High order bit thing? I've searched for similar threads, but I must say that I don't understand what's cooking here. Please help. Thanks.
Keith Renecle
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
Does the 12f675 have a separate regulated battery voltage? If not, then you will be trying to pin down a moving target/battery voltage, unless a constant reference voltage is supplied.
Both of the a-d.h and eeprom.h files needed fixing for the low pin count devices a while back. Here is the eeprom fix http://sourceforge.net/forum/message.php?msg_id=5042385. Hugh fixed the eeprom.h file about the same time for 18f table reads, so my fix did not include that, and not sure if his fix included mine.
If you have the microchip low pin count (LPC) board, be careful of the on-board pot. I have twisted mine back in forth enough that it has become unreliable. They are only made for 200 operations or so.
If the eeprom.h file doesn't work, then I could send you an a-d.h file that does appear to work with the above eeprom fix. This file includes a working AVR a-d (continous conversion) with a minor fix.
Some of my files are a real mess, since the hard drive gave up in the laptop.
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
Hi Kent, Thanks so much for the help again. I really appreciate it. I realised soon enough about the crappy pot on the demo board.
I have learned plenty from your program, and now my program is reading and writing up to 3E in a single eeprom location. My next question is...How does the input votage actually relate to what is going into the "write function?" It does not appear to be linear if I measure it with a voltmeter and compare.
What is the actual voltage range that I can feed into the chip? Is it the maximum supply voltage of around 5.0 volts? I know that it is a 10 bit A/D (1024), so does this mean that I can just put 1.024 volts on the actual pin?
In my program, I did not use this line below:
#config _CP_OFF & _CPD_OFF & _BODEN_OFF & _WDT_OFF & _PWRTE_ON & _INTRC_OSC_NOCLKOUT
Do I need to do this always? Thanks,
Keith
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
O.K. I played around a little more, and I noticed that with your program as it is, the eeprom location 1 has 00 in it, with the pot turned full to + volts. The next location goes up to 43 Hex. Just by the way, the supply for my project comes from a regulator in the speed controller. The refer to this as a BEC (Battery Eliminator Circuit), and it is used to feed the receiver and servo's in the models.
So, my pot can give 0 to 4.0 volts to the pin for AN(0) via a 1K resistor. So now I still can't figure out the high/low order byte thing.
Line 19 in your program says :
EPWrite(EEPromCount, Volt_H) 'low pin count devices have byte size EEProm addresses
I thought each eeprom location was 2bytes = FF?
When you say "Volt_H", I suppose this means the high order byte, and if there are always zero's in this memory location, does this then mean that my voltage is too low to read anything in the high order byte?
The other thing that I have not seen before, is this line:
EEPromCount += 1
Is this similar to a for/next loop? (My last encounter with programming was with Applesoft Basic on the old Apple 2 Plus, so please forgive the stoopid questions)
Keith
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
Hey Keith, a couple of questions, did you have to use the linked eeprom.h? and do you have a model number or link for your ESC? Curious to know more about the RC stuff.
Will try to answer your questions and how it relates to the previously linked example program.
1) Many of the LPC devices have only byte sized EEPROM addresses. So when sending 10bit or word sized variables, the variable needs to be broken down into into the high byte (Volt_H) and low byte (Volt). The midrange devices and up, have word sized addresses or registers.
2) When hooked up to the LPC demo board and its four led's, turning the pot full on produces Volt_H = b'00000011' (0x03), and Volt = b'11111111' (0xFF). When the EEPROM is read back, the Volt_H and Volt are reassembled back into a word variable (0x3FF), and the MSb's are read out on the led's. So the "LED" result for this example equals 256* b'00000011'+ b'11xxxxxx' or 0x3C0. Hopefully that explains the high and low order byte thing for you.
If all the led's are not turned on (or getting 0x3FF), then its because of the crummy pot, try pressing on one side or another.
3) When the battery's are new/freshly charged, what is the max voltage? Just remember when reading the a-d, that the default range is going to be 0-Vdd or the ESC voltage. You could use a voltage divider on the ESC voltage to output your 4.0V to the Vref pin after its enabled. That would improve your resolution, 4/1024 = 3.91mv/bit vs. 5/1024 = 4.88mv/bit.
The battery voltage or analog input is limited by the Vdd (5V) or possibly a Vref(4V?) if enabled. If a higher voltage analog voltage needed to be sampled then it would have to be reduced by a voltage divider. If the battery voltage exceeded the reference voltage, then I would expect a zero or an unreliable number.
4) EEPromCount +=1 is the same as EEPromCount = EEPromCount + 1.
5) Just need the internal oscillator config at the min, having the power up timer enabled may, or may not be beneficial in stabilizing the internal oscillator so: #config _PWRTE_ON & _INTRC_OSC_NOCLKOUT
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
Thanks again. The +=1 thing is neat. I replaced the eeprom.h file with yours, and it does the same thing. The high order byte does nothing. Maybe my rogram is wrong.Here is my basic test program:
'Test eeprom locations
#chip 12F675, 4
#config Osc = Int
dir GPIO.0 in
dim num as word
Checkad:
num = ReadAD10(AN0)
EPWrite (0, num_H)
EPWrite (1, num)
Goto Checkad
I don't use the LED's on this, but simply check what's in the memory location with the Pickit2 software. BTW I replaced the cheap pot, and the supply for this prject just comes from the USB socket and proto board. On my model circuit, the esc has the 4.8 volt regulator that is rock solid. I understand that I need a voltage divider that comes from the battery pack. Most of my electric motors run on either a 3-cell (11.1V) or 4-cell (14.8V) Lipo battery.
If you want info on the esc's then just Google "Brushless motor esc" and you'll have hundreds of links. I have a Jeti Spin 44 and a Hobbywing Pentium 60. The Jeti has the governor and brake modes, but this was modified by the factory to have both modes. The governor or constant speed mode is mainly for the helicopter pilots who fly the so-called 3-D aerobatics. The rotor maintains a constant speed and the pilot varies the pitch, which obviously changes the load drastically. They even use negative pitch to fly inverted. They don't allow the brake mode because the pilot could inadvertently stop the rotor blades. In control-line aerobatics, we need the constant speed, but the international rules require the motor to stop the propeller before touch-down.
If you need more info then I can provide this for you. Thanks.
Keith
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
O.K. so now I tried this again and included a delay (wait 20 ms). Now it reads "00 3E" with the pot turned full on. This relates to 62 decimal. I removed the Read AD function and just entered "num = 512" for example. The eeprom then shows 02 00, and this shows that I am indeed writing correctly to the eeprom. Does the fact that it shows 00 3E when I read the AN(0)pin mean that this is what the AD is actually reading?
Here is my present, revised test program:
'Test eeprom locations
#chip 12F675, 4
#config Osc = Int
dir GPIO.0 in
dim num as word
Checkad:
num = ReadAD10(AN0)
EPWrite (0, num_H)
EPWrite (1, num)
wait 20 ms
Goto Checkad
Just one more question, I tried to poke this value into another program memory location using POKE (location, num). I tried various memory locations and I always get a syntax error message when compiling. How do I do this? Thanks again.
Keith
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
Using your program and reading my 12f683 device on the Pickit 2, my best was 03 E3, with the pot full on. Problem is that it will only compile with my newer a-d.h file. Because my files are in such bad shape, not sure what the lastest update zip a-d.h file even looks like now. The a-d.h should work tho because I posted in the compiler forum thinking it didn't, but had not properly updated the zip file, and of course it worked.
If you were to register for an account on sourceforge, I would be happy to e-mail my a-d.h file, if you think it would help. Their accounts use a forwarding scheme to protect ones e-mail address. No way to post this file because its 10kb long, and message posts lose all code formatting, which would make it unreadable.
Haven't tried poking registers before.
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
Thanks for the a-d.h file Kent. I have not yet tried it, but what I did in fact do was to read the AN(0) port from the pot and drive the servo back and forth. It runs less than the normal 1 mS position and also more than the standard 2 mS position. This means that it must be feeding my program with numbers from below 100 to above 200, because this is what it requires for the servo.
To double check this, I put the output pin into my scope, and the pulse width does go from just below 1 to above 2 mS with a 20 mS fram rate. I also write this value into eeprom locations 0 and 1, but I just get the same 00 3E. Therefore, I reckon that the problem has to do with the way that I am writing this value into the eeprom. and not the way that my program is reading AN(0). Here is my test program below:
#chip 12F675, 4
#config Osc = Int
#define RpmPin GPIO.1
Dir RpmPin Out
Dim ServoT as word
Runservo:
ServoT = ReadAD10(AN0)
PulseOut RpmPin, servoT 10us 'ServoT is pulse width * 10us
EPWrite (0, ServoT)
Wait 20 ms
Goto Runservo
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
Whoops! sent response to the monitoring e-mail, so here it is for the forum:
Well it looks like you have changed gears here from reading the battery.
Really don't want to get into the whole constant speed controller thing, other then if some part of GCBasic isn't working for you. There is going to be some math involved to treat the battery voltage number against some rpm/volt difference (from full charge) and adding/updating that to your servo position/speed. Best of luck.
From a first look at the code, a word variable is trying to be stuffed into a byte sized eeprom location (its the low pin count thing). This was explained and shown in previous example on how to send a word variable to eeprom.
In this case "EPWrite (0, ServoT)" only the lower byte of a word variable is getting thru. Best to use only a byte size variable here, so for test purposes, then ServoT = ReadAD(AN0). Conditional statements will limit the travel to the 1ms-2ms range. If you have your motor(s) setup this way previously, that should be apparent. Like:
If ServoT >= 200 then PulseOut RpmPin, 200 10us
If ServoT < 200 AND ServoT > 100 then PulseOut RpmPin, servoT 10us
If ServoT <= 100 then PulseOut RpmPin, 100 10us
Haven't tried this code, and sometimes there is no road map but experimentation and trial and error on your part.
A word of caution on the limited variable space available of the 12f675. Check the assembler file (with its the equate/register numbers) against the SRAM available to see how close to the limit.
Regards,
Kent
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
Hi All,
Thanks to Hugh and Kent for the regular help on this forum, I have been able to use GCBasic to make some decent working timing circuits for my control-line model planes with electric motors. The electronic speed controllers (esc's) normally require a 1 to 2 ms signal from an R/C receiver, but we don't use any R/C stuff on control-line, so we need a timer to set the flight time and also the motor speed.
I've managed to program PIC 12F675 chips that work very well and do almost all of my needs........but....(and there is always a "but") I now need to compensate for the battery voltage dropping over the flight time by reading the value from one of the AN ports. You can in fact buy esc's with a governor mode that keeps the motor speed constant, but I would like to try this another way.
O.K Here's the problem. I wrote a simple routine to run the servo by reading the AN(0) port, and then using the result to run a servo backwards and forwards. I use a servo because it's easier that going to my workshop and hooking up a scope. The pot is on the Pickit2 proto board, and if I stay in the centre range of the pot, the servo works o.k. To see what the voltage is read as, I write the value to the first eeprom memory, and then read it with the Pickit software. For a voltage range of 0 to 3.8 volts, I get 0 to 0C Hex. The numbers to run the servo are 100 to 200 with are multiplied by 10 us.
So...what on earth am I putting into the eeprom? The servo works between the 2 extremes, so why can't I store this value as is? Is this a Low/High order bit thing? I've searched for similar threads, but I must say that I don't understand what's cooking here. Please help. Thanks.
Keith Renecle
Does the 12f675 have a separate regulated battery voltage? If not, then you will be trying to pin down a moving target/battery voltage, unless a constant reference voltage is supplied.
Both of the a-d.h and eeprom.h files needed fixing for the low pin count devices a while back. Here is the eeprom fix http://sourceforge.net/forum/message.php?msg_id=5042385. Hugh fixed the eeprom.h file about the same time for 18f table reads, so my fix did not include that, and not sure if his fix included mine.
If you have the microchip low pin count (LPC) board, be careful of the on-board pot. I have twisted mine back in forth enough that it has become unreliable. They are only made for 200 operations or so.
If the eeprom.h file doesn't work, then I could send you an a-d.h file that does appear to work with the above eeprom fix. This file includes a working AVR a-d (continous conversion) with a minor fix.
Some of my files are a real mess, since the hard drive gave up in the laptop.
Hi Kent, Thanks so much for the help again. I really appreciate it. I realised soon enough about the crappy pot on the demo board.
I have learned plenty from your program, and now my program is reading and writing up to 3E in a single eeprom location. My next question is...How does the input votage actually relate to what is going into the "write function?" It does not appear to be linear if I measure it with a voltmeter and compare.
What is the actual voltage range that I can feed into the chip? Is it the maximum supply voltage of around 5.0 volts? I know that it is a 10 bit A/D (1024), so does this mean that I can just put 1.024 volts on the actual pin?
In my program, I did not use this line below:
#config _CP_OFF & _CPD_OFF & _BODEN_OFF & _WDT_OFF & _PWRTE_ON & _INTRC_OSC_NOCLKOUT
Do I need to do this always? Thanks,
Keith
O.K. I played around a little more, and I noticed that with your program as it is, the eeprom location 1 has 00 in it, with the pot turned full to + volts. The next location goes up to 43 Hex. Just by the way, the supply for my project comes from a regulator in the speed controller. The refer to this as a BEC (Battery Eliminator Circuit), and it is used to feed the receiver and servo's in the models.
So, my pot can give 0 to 4.0 volts to the pin for AN(0) via a 1K resistor. So now I still can't figure out the high/low order byte thing.
Line 19 in your program says :
EPWrite(EEPromCount, Volt_H) 'low pin count devices have byte size EEProm addresses
I thought each eeprom location was 2bytes = FF?
When you say "Volt_H", I suppose this means the high order byte, and if there are always zero's in this memory location, does this then mean that my voltage is too low to read anything in the high order byte?
The other thing that I have not seen before, is this line:
EEPromCount += 1
Is this similar to a for/next loop? (My last encounter with programming was with Applesoft Basic on the old Apple 2 Plus, so please forgive the stoopid questions)
Keith
Hey Keith, a couple of questions, did you have to use the linked eeprom.h? and do you have a model number or link for your ESC? Curious to know more about the RC stuff.
Will try to answer your questions and how it relates to the previously linked example program.
1) Many of the LPC devices have only byte sized EEPROM addresses. So when sending 10bit or word sized variables, the variable needs to be broken down into into the high byte (Volt_H) and low byte (Volt). The midrange devices and up, have word sized addresses or registers.
2) When hooked up to the LPC demo board and its four led's, turning the pot full on produces Volt_H = b'00000011' (0x03), and Volt = b'11111111' (0xFF). When the EEPROM is read back, the Volt_H and Volt are reassembled back into a word variable (0x3FF), and the MSb's are read out on the led's. So the "LED" result for this example equals 256* b'00000011'+ b'11xxxxxx' or 0x3C0. Hopefully that explains the high and low order byte thing for you.
If all the led's are not turned on (or getting 0x3FF), then its because of the crummy pot, try pressing on one side or another.
3) When the battery's are new/freshly charged, what is the max voltage? Just remember when reading the a-d, that the default range is going to be 0-Vdd or the ESC voltage. You could use a voltage divider on the ESC voltage to output your 4.0V to the Vref pin after its enabled. That would improve your resolution, 4/1024 = 3.91mv/bit vs. 5/1024 = 4.88mv/bit.
The battery voltage or analog input is limited by the Vdd (5V) or possibly a Vref(4V?) if enabled. If a higher voltage analog voltage needed to be sampled then it would have to be reduced by a voltage divider. If the battery voltage exceeded the reference voltage, then I would expect a zero or an unreliable number.
4) EEPromCount +=1 is the same as EEPromCount = EEPromCount + 1.
5) Just need the internal oscillator config at the min, having the power up timer enabled may, or may not be beneficial in stabilizing the internal oscillator so: #config _PWRTE_ON & _INTRC_OSC_NOCLKOUT
Thanks again. The +=1 thing is neat. I replaced the eeprom.h file with yours, and it does the same thing. The high order byte does nothing. Maybe my rogram is wrong.Here is my basic test program:
'Test eeprom locations
#chip 12F675, 4
#config Osc = Int
dir GPIO.0 in
dim num as word
Checkad:
num = ReadAD10(AN0)
EPWrite (0, num_H)
EPWrite (1, num)
Goto Checkad
I don't use the LED's on this, but simply check what's in the memory location with the Pickit2 software. BTW I replaced the cheap pot, and the supply for this prject just comes from the USB socket and proto board. On my model circuit, the esc has the 4.8 volt regulator that is rock solid. I understand that I need a voltage divider that comes from the battery pack. Most of my electric motors run on either a 3-cell (11.1V) or 4-cell (14.8V) Lipo battery.
If you want info on the esc's then just Google "Brushless motor esc" and you'll have hundreds of links. I have a Jeti Spin 44 and a Hobbywing Pentium 60. The Jeti has the governor and brake modes, but this was modified by the factory to have both modes. The governor or constant speed mode is mainly for the helicopter pilots who fly the so-called 3-D aerobatics. The rotor maintains a constant speed and the pilot varies the pitch, which obviously changes the load drastically. They even use negative pitch to fly inverted. They don't allow the brake mode because the pilot could inadvertently stop the rotor blades. In control-line aerobatics, we need the constant speed, but the international rules require the motor to stop the propeller before touch-down.
If you need more info then I can provide this for you. Thanks.
Keith
O.K. so now I tried this again and included a delay (wait 20 ms). Now it reads "00 3E" with the pot turned full on. This relates to 62 decimal. I removed the Read AD function and just entered "num = 512" for example. The eeprom then shows 02 00, and this shows that I am indeed writing correctly to the eeprom. Does the fact that it shows 00 3E when I read the AN(0)pin mean that this is what the AD is actually reading?
Here is my present, revised test program:
'Test eeprom locations
#chip 12F675, 4
#config Osc = Int
dir GPIO.0 in
dim num as word
Checkad:
num = ReadAD10(AN0)
EPWrite (0, num_H)
EPWrite (1, num)
wait 20 ms
Goto Checkad
Just one more question, I tried to poke this value into another program memory location using POKE (location, num). I tried various memory locations and I always get a syntax error message when compiling. How do I do this? Thanks again.
Keith
Using your program and reading my 12f683 device on the Pickit 2, my best was 03 E3, with the pot full on. Problem is that it will only compile with my newer a-d.h file. Because my files are in such bad shape, not sure what the lastest update zip a-d.h file even looks like now. The a-d.h should work tho because I posted in the compiler forum thinking it didn't, but had not properly updated the zip file, and of course it worked.
If you were to register for an account on sourceforge, I would be happy to e-mail my a-d.h file, if you think it would help. Their accounts use a forwarding scheme to protect ones e-mail address. No way to post this file because its 10kb long, and message posts lose all code formatting, which would make it unreadable.
Haven't tried poking registers before.
Thanks for the a-d.h file Kent. I have not yet tried it, but what I did in fact do was to read the AN(0) port from the pot and drive the servo back and forth. It runs less than the normal 1 mS position and also more than the standard 2 mS position. This means that it must be feeding my program with numbers from below 100 to above 200, because this is what it requires for the servo.
To double check this, I put the output pin into my scope, and the pulse width does go from just below 1 to above 2 mS with a 20 mS fram rate. I also write this value into eeprom locations 0 and 1, but I just get the same 00 3E. Therefore, I reckon that the problem has to do with the way that I am writing this value into the eeprom. and not the way that my program is reading AN(0). Here is my test program below:
#chip 12F675, 4
#config Osc = Int
#define RpmPin GPIO.1
Dir RpmPin Out
Dim ServoT as word
Runservo:
ServoT = ReadAD10(AN0)
PulseOut RpmPin, servoT 10us 'ServoT is pulse width * 10us
EPWrite (0, ServoT)
Wait 20 ms
Goto Runservo
Whoops! sent response to the monitoring e-mail, so here it is for the forum:
Well it looks like you have changed gears here from reading the battery.
Really don't want to get into the whole constant speed controller thing, other then if some part of GCBasic isn't working for you. There is going to be some math involved to treat the battery voltage number against some rpm/volt difference (from full charge) and adding/updating that to your servo position/speed. Best of luck.
From a first look at the code, a word variable is trying to be stuffed into a byte sized eeprom location (its the low pin count thing). This was explained and shown in previous example on how to send a word variable to eeprom.
In this case "EPWrite (0, ServoT)" only the lower byte of a word variable is getting thru. Best to use only a byte size variable here, so for test purposes, then ServoT = ReadAD(AN0). Conditional statements will limit the travel to the 1ms-2ms range. If you have your motor(s) setup this way previously, that should be apparent. Like:
If ServoT >= 200 then PulseOut RpmPin, 200 10us
If ServoT < 200 AND ServoT > 100 then PulseOut RpmPin, servoT 10us
If ServoT <= 100 then PulseOut RpmPin, 100 10us
Haven't tried this code, and sometimes there is no road map but experimentation and trial and error on your part.
A word of caution on the limited variable space available of the 12f675. Check the assembler file (with its the equate/register numbers) against the SRAM available to see how close to the limit.
Regards,
Kent