leaveme
Junior Member
Offline
Posts: 93
Thank You
-Given: 38
-Receive: 15
|
|
« on: December 07, 2011, 08:06:24 08:06 » |
|
Hi, I need to make an AC/Universal motor controller with RPM count. In the first phase I started coding for tacho part. But my tacho is very unstable. I attached the coding and proteus file. Please help. // CCS PCWHD Compiler 4.057 // ------------------------
#include <16F886.H>
#fuses HS //High speed Osc (> 4mhz for PCM/PCH) #fuses NOBROWNOUT //No brownout reset #fuses NOPROTECT //Code not protected from reading #fuses NOLVP //No low voltage programing, B3(PIC16) #fuses NOWDT //No Watch Dog Timer //#FUSES NOPUT //No Power Up Timer
#use delay(clock=20M) //20Mhz crystal
// #priority CCP1, TIMER1, RB // Set interrupt priority
#include <flex_LCD.c>
// Tach reading int16 isr_ccp_delta; #int_ccp1 void ccp1_isr(void) { int16 current_ccp; static int16 old_ccp = 0;
// Read the 16-bit hardware CCP1 register current_ccp = CCP_1; isr_ccp_delta = current_ccp - old_ccp;
// Save the current ccp value for the next pass old_ccp = current_ccp; }
//Main function starts here void main(void) { int16 current_ccp_delta; int16 rev;
lcd_init(); //LCD start lcd_putc("\f"); // Clear the LCD delay_ms(100);
set_timer1(0); setup_timer_1(T1_INTERNAL | T1_DIV_BY_1); // T1_DIV_BY_8 to reduce the lower limit on the RPM range setup_ccp1(CCP_CAPTURE_RE);
clear_interrupt(INT_CCP1); enable_interrupts(INT_CCP1); enable_interrupts(GLOBAL);
while(1) { disable_interrupts(GLOBAL); current_ccp_delta = isr_ccp_delta; enable_interrupts(GLOBAL); rev = (int16)(5000000L / current_ccp_delta); //period in seconds rev *= 60; // period in minutes lcd_gotoxy(1,1); //Goto first line printf(lcd_putc, "%lu RPM ", rev); // Display RPM
delay_ms(100);
}
}
|
|
|
Logged
|
|
|
|
solutions
Hero Member
Offline
Posts: 1824
Thank You
-Given: 656
-Receive: 903
|
|
« Reply #1 on: December 07, 2011, 03:13:36 15:13 » |
|
Change your display update to 1 second in the last loop, and also average at least 10 RPM computations, for starters
|
|
|
Logged
|
|
|
|
TomJackson69
Active Member
Offline
Posts: 218
Thank You
-Given: 26
-Receive: 63
|
|
« Reply #2 on: December 07, 2011, 04:15:08 16:15 » |
|
leaveme,
Please attach the HEX file, I want to take a look at your circuit in simulation.
Tom
|
|
|
Logged
|
Con Rong Chau Tien
|
|
|
leaveme
Junior Member
Offline
Posts: 93
Thank You
-Given: 38
-Receive: 15
|
|
« Reply #3 on: December 07, 2011, 04:20:35 16:20 » |
|
Thanks solutions. I really need fast RPM display. Is there anything else I should look into...
|
|
|
Logged
|
|
|
|
Ichan
Hero Member
Offline
Posts: 833
Thank You
-Given: 312
-Receive: 392
|
|
« Reply #4 on: December 07, 2011, 04:34:51 16:34 » |
|
Hi Leaveme,
Not everyone use CCS, so as Tom said including the hex file will open more chance to catch the bug.
I don't use ccs myself, my blind guess: try to move both current_ccp_delta and isr_ccp_delta as global and volatile variable.
-ichan
|
|
|
Logged
|
There is Gray, not only Black or White.
|
|
|
TomJackson69
Active Member
Offline
Posts: 218
Thank You
-Given: 26
-Receive: 63
|
|
« Reply #5 on: December 07, 2011, 05:00:31 17:00 » |
|
leaveme,
I am waiting for your HEX file.
Tom
|
|
|
Logged
|
Con Rong Chau Tien
|
|
|
leaveme
Junior Member
Offline
Posts: 93
Thank You
-Given: 38
-Receive: 15
|
|
« Reply #6 on: December 07, 2011, 05:15:26 17:15 » |
|
Ok buddy, I attached the HEX and LST file both. Hope it will help. Hey Tom, how are you? After long long time...
|
|
|
Logged
|
|
|
|
TomJackson69
Active Member
Offline
Posts: 218
Thank You
-Given: 26
-Receive: 63
|
|
« Reply #7 on: December 07, 2011, 05:50:15 17:50 » |
|
leaveme, I don't use CCS so I can not modify your code right now. I can convert it to C18 and use 18F452 to test your code, but it will take sometimes. Meanwhile, you can modify your code so that TMR1 will interrupt every 1/10 second or 1/20 seconds (or whatever you like, but even number is better). Like ichan said "try to move both current_ccp_delta and isr_ccp_delta as global and volatile variable". They should be global variables. Also, the "static int16 old_ccp = 0;" line in the interrupt routine could be . The "old_ccp" should be reset to zero the new count. The interrupt routine seem like not very good. I would suggest to read "CCP_1" 10 or 20 times than take an average of the reading. That average is a reading of 1 second or 1/2 second or whatever time base you set for interrupt. Let say every 1/2 second you get the average reading than set a flag to 1 indicate that a half second has occured and a reading is ready for you to display. In main, a while loop is waiting for that flag to set. After display, clear the flag and it keep repeating. Hope I have time to modify your code. Tom
|
|
|
Logged
|
Con Rong Chau Tien
|
|
|
solutions
Hero Member
Offline
Posts: 1824
Thank You
-Given: 656
-Receive: 903
|
|
« Reply #8 on: December 08, 2011, 12:08:34 00:08 » |
|
Thanks solutions. I really need fast RPM display. Is there anything else I should look into...
A fast display is useless if you cannot read it. Tom seems to have agreed with what I originally posted, but he apparently like Ichan more than me : "I would suggest to read "CCP_1" 10 or 20 times than take an average of the reading. That average is a reading of 1 second or 1/2 second or whatever time base you set for interrupt." Motors jump from pole to pole. You cannot infer an RPM reading if you measure on a short time interval. There's too much mechanical jitter, aka vibration. In other words, what you want, a "fast readout", you cannot get. IMPOSSIBLE. You can average, but that average is not the "instantaneous" RPM, it's a historical one. You also did not explain why you need this fast readout. Do you have Superman on the motor speed control?
|
|
|
Logged
|
|
|
|
TomJackson69
Active Member
Offline
Posts: 218
Thank You
-Given: 26
-Receive: 63
|
|
« Reply #9 on: December 08, 2011, 12:50:01 00:50 » |
|
Like solutions has said "what you want, a "fast readout", you cannot get. IMPOSSIBLE. ". Also WHY??? You are wasting the uP time by displaying the reading more than twice/second; unless you want to animate somethings.
I have a question: What is the MAX SPEED of your motor? in other word, what is MAX FREQUENCY of the pulse output of the motor and single phase or three phases???
Tom
|
|
|
Logged
|
Con Rong Chau Tien
|
|
|
leaveme
Junior Member
Offline
Posts: 93
Thank You
-Given: 38
-Receive: 15
|
|
« Reply #10 on: December 08, 2011, 05:31:07 05:31 » |
|
@solutions: I'll use the tach readout for speed feedback. So, fast is better. Slow readout will give a wobble effect in the motor speed. @Tom: Speed range of the motor will be 5K - 30K RPM. It is a single phase (brussed) AC/Universal motor. The motor is rated for 220v/30K RPM. My main goal is building a speed controller with speed feedback. I'll use a reflective sensor for the rotation count. RPM data then will be used to maintain a constant speed. 2-3% speed variation is ok. Zero crossing need to be used for triac firing though I never worked with it before. Say, I referenced the motor to run at 5K RPM and it will do so but without load. The speed will decrease as soon as there is a (side) load since the motor has a cutter attached to it. Speed controller counts the RPM and immediately increase necessary power until the speed reaches to the referenced value. Edit: Anybody used T1G (pin # 26) of 16F886 before? Someone suggested me to use T1G for precise RPM count.
|
|
« Last Edit: December 08, 2011, 05:53:31 05:53 by leaveme »
|
Logged
|
|
|
|
solutions
Hero Member
Offline
Posts: 1824
Thank You
-Given: 656
-Receive: 903
|
|
« Reply #11 on: December 08, 2011, 10:01:14 22:01 » |
|
@solutions: I'll use the tach readout for speed feedback. So, fast is better. Slow readout will give a wobble effect in the motor speed. @Tom: Speed range of the motor will be 5K - 30K RPM. It is a single phase (brussed) AC/Universal motor. The motor is rated for 220v/30K RPM. My main goal is building a speed controller with speed feedback. I'll use a reflective sensor for the rotation count. RPM data then will be used to maintain a constant speed. 2-3% speed variation is ok. Zero crossing need to be used for triac firing though I never worked with it before. Say, I referenced the motor to run at 5K RPM and it will do so but without load. The speed will decrease as soon as there is a (side) load since the motor has a cutter attached to it. Speed controller counts the RPM and immediately increase necessary power until the speed reaches to the referenced value. Edit: Anybody used T1G (pin # 26) of 16F886 before? Someone suggested me to use T1G for precise RPM count. You sure are knocking yourself out when all you need is an opamp.....
|
|
|
Logged
|
|
|
|
TomJackson69
Active Member
Offline
Posts: 218
Thank You
-Given: 26
-Receive: 63
|
|
« Reply #12 on: December 09, 2011, 03:56:09 15:56 » |
|
leaveme,
Try solution suggestions to see how it works.
But, if you still want to use software than a PID control is a sure way to control the motor. Without PID, you will have hard time to maintain the speed of the motor. Try to manually control the fan speed with a knob to see how hard it is.
Tom
|
|
|
Logged
|
Con Rong Chau Tien
|
|
|
leaveme
Junior Member
Offline
Posts: 93
Thank You
-Given: 38
-Receive: 15
|
|
« Reply #13 on: December 09, 2011, 04:35:02 16:35 » |
|
Thanx Tom. At the end it will be a PID controller. But I'm experimenting each part individually so that I'll be sure that I'm in the right direction. I'll modify the coding as per you guys earlier suggestion. Let's see what happens... I'll keep you posted.
|
|
|
Logged
|
|
|
|
TomJackson69
Active Member
Offline
Posts: 218
Thank You
-Given: 26
-Receive: 63
|
|
« Reply #14 on: December 10, 2011, 01:01:47 01:01 » |
|
Leaveme,
I don’t have CSS installed on my computer so I can not modify your program. Here is what I would do if I am going to modify it.
Global variables: Pulse_Counter, Total_P_Counter and Int_Counter,
1. Use TMR1 as a timer for interrupts every 10mS (or whatever time you want). 2. Use RB0 (any free pin on port B) as Pin Change Interrupt and set as Hi-Priority Int. (edge level H/L not mater). 3. Each Pin Change Interrupt on RB0, increase Pulse_Counter by one (make sure Pulse_Counte big enough). 4. Each TMR1 int, add Pulse_Counter to Total_P_Counter, set Pulse_Counter = 0 and increase Int_Counter by one. When Int_Counter = 10, set Int_Counter = 0 (in TMR1 int). Calculate RPM base on Total_P_Counter and TMR1 period than reset Total_P_Counter = 0 (remember Total_P_Counter is for 10 reading).
This should works and will have some error on very slow speed. For RPM = 25,000 should be OK. Display your RPM reading every 1/3 or ½ or 1 second is up to you in the main loop.
Tom
|
|
« Last Edit: December 10, 2011, 03:12:37 03:12 by TomJackson69 »
|
Logged
|
Con Rong Chau Tien
|
|
|
leaveme
Junior Member
Offline
Posts: 93
Thank You
-Given: 38
-Receive: 15
|
|
« Reply #15 on: December 10, 2011, 04:39:22 04:39 » |
|
Thanx Tom once again. UPDATE:I got the Tacho working and it is perfect now. 2nd phase is Speed Controller. Anybody knows a good DIMMER in C, which will help me a lot.
|
|
« Last Edit: December 10, 2011, 08:54:55 08:54 by leaveme »
|
Logged
|
|
|
|
iphone
Active Member
Offline
Posts: 168
Thank You
-Given: 115
-Receive: 10
|
|
« Reply #16 on: December 10, 2011, 09:02:39 09:02 » |
|
Thanx Tom once again. UPDATE:I got the Tacho working and it is perfect now. 2nd phase is Speed Controller. Anybody knows a good DIMMER in C, which will help me a lot. In my experience, to control speed, I'm using PWM with variable Duty %.
|
|
|
Logged
|
|
|
|
leaveme
Junior Member
Offline
Posts: 93
Thank You
-Given: 38
-Receive: 15
|
|
« Reply #17 on: December 10, 2011, 09:07:46 09:07 » |
|
In my experience, to control speed, I'm using PWM with variable Duty %.
It is an AC/Universal single phase motor. PWM will not work. I need phase control method.
|
|
|
Logged
|
|
|
|
TomJackson69
Active Member
Offline
Posts: 218
Thank You
-Given: 26
-Receive: 63
|
|
« Reply #18 on: December 10, 2011, 06:17:23 18:17 » |
|
leaveme,
Try U208B Phase Control to see if it works.
Tom
|
|
|
Logged
|
Con Rong Chau Tien
|
|
|
leaveme
Junior Member
Offline
Posts: 93
Thank You
-Given: 38
-Receive: 15
|
|
« Reply #19 on: December 11, 2011, 04:36:09 04:36 » |
|
leaveme,
Try U208B Phase Control to see if it works.
Tom
Thanks buddy. Since it will be a PID controller so I can't move to U208B. I have a MCU for tacho and I need to use the same unit for phase control too. If you know anything PIC based, please share.
|
|
|
Logged
|
|
|
|
TomJackson69
Active Member
Offline
Posts: 218
Thank You
-Given: 26
-Receive: 63
|
|
« Reply #20 on: December 11, 2011, 05:55:54 05:55 » |
|
The U208B is a phase control that will directly control the phase angle for the load. I forget how it really works but, I think it has a pin that you can control by varry the voltage. That in turn, you can use PWM to control the phase angle.
The PID control will fit nicely to the U208B. Since PWM can be convert to voltage and this voltage can control the U208B. That way you don't have to worry about detecting zero crossing and when to turn on the TRIAC (or SCRs) and so on...
You can take a look at the dat sheet to really undrestand.
Tom
|
|
|
Logged
|
Con Rong Chau Tien
|
|
|
leaveme
Junior Member
Offline
Posts: 93
Thank You
-Given: 38
-Receive: 15
|
|
« Reply #21 on: December 11, 2011, 09:50:14 09:50 » |
|
I just checked the datasheet. It seems to me better for independant application. But in my case, I prefer to avoide external components as much as possible. Besides, my mcu is un-utilized.
|
|
|
Logged
|
|
|
|
leaveme
Junior Member
Offline
Posts: 93
Thank You
-Given: 38
-Receive: 15
|
|
« Reply #22 on: December 13, 2011, 07:23:52 07:23 » |
|
Hi, Anybody here knows CCS C? Pls help me for a dimmer/motor speed control. I also attached the simulation file. I can't really get the zero crossing synchronization implemented. #include <16F886.H> // #include <16F88.H>
#fuses HS,NOWDT,NOPUT,NOLVP,NOBROWNOUT,NOWRT #use delay(clock=20M)
//#use fast_io(A) //#use fast_io(B)
//#byte PORTA = 0x05 //#byte PORTB = 0x06 //#byte ANSEL = 0x9B //#byte OPTIONREG = 0x81
#define LCD_DB4 PIN_B1 #define LCD_DB5 PIN_B2 #define LCD_DB6 PIN_B3 #define LCD_DB7 PIN_B4
#define LCD_E PIN_C5 #define LCD_RS PIN_C4 #define LCD_RW PIN_C6
#include <flex_LCD.c>
#define HZ 50
#define PORT_adc sAN0 // PIN_A0 #define PORT_zero PIN_B0 #define TRIAC PIN_B7 #define ON output_high #define OFF output_low
#define Int_Min 50 // 50 #define Int_Max 80 // 80 #define period 85 // 85
int8 dim_pos; int8 intensity;
#INT_EXT void zerocross() { dim_pos=0; if (PORT_zero) ext_int_edge(H_TO_L); else ext_int_edge(L_TO_H); }
#INT_TIMER0 void triggure(){ set_timer0(period); dim_pos++; if (dim_pos==intensity){ ON(TRIAC); delay_us(20); OFF(TRIAC); } }
void main(void) { // Port directions: 1=input, 0=output set_tris_a( 0b00000001 ); set_tris_b( 0b00000001 );
// Setup the ADC so we can read a value from 0 to 1023 // as we turn a trimpot which is connected to pin A0. setup_comparator(NC_NC_NC_NC); setup_adc_ports(PORT_adc); setup_adc(ADC_CLOCK_DIV_32); // Divisor for 20 MHz oscillator set_adc_channel(0); delay_us(15);
lcd_init(); //LCD start lcd_putc("\f"); // Clear the LCD delay_ms(100); lcd_gotoxy(1,1); //Goto first line printf(lcd_putc, "Intensity");
// ANSEL=0; // OPTIONREG=OPTIONREG & 0x7F;
setup_timer_0(RTCC_INTERNAL | RTCC_DIV_2); // setup_timer_0( T0_INTERNAL| T0_DIV_64 | T0_8_BIT );
enable_interrupts(INT_TIMER0); enable_interrupts(INT_EXT); ext_int_edge(L_TO_H); enable_interrupts(GLOBAL); set_timer0(period); intensity = Int_Max ; while(1) { // intensity = read_adc(); // Read speed set value from the ADC
// lcd_gotoxy(1,2); //Goto second line // printf(lcd_putc, "%lu ", intensity); //Show intensity for test perpose // delay_ms(10); } }
|
|
|
Logged
|
|
|
|
solutions
Hero Member
Offline
Posts: 1824
Thank You
-Given: 656
-Receive: 903
|
|
« Reply #23 on: December 13, 2011, 05:57:31 17:57 » |
|
What is the maximum desired RPM of your lamp?
Seriously - why are you saying "dimmer/motor" control. I thought you were doing an AC MOTOR control. A dimmer is a totally different approach - you can't just cut and paste dimmer code....you yourself said you need phase control. A phase controlled dimmer is NOT the same as phase controlled motor speed.
I suggest you look at app notes from TI, ATMEL and others on AC motor speed control. Most have example code. It's NOT, however, the same as a dimmer.
|
|
|
Logged
|
|
|
|
leaveme
Junior Member
Offline
Posts: 93
Thank You
-Given: 38
-Receive: 15
|
|
« Reply #24 on: December 13, 2011, 06:10:46 18:10 » |
|
If it is a dimmer then I can at least understand the phase control concept, i.e. how zero cross synchronized...
|
|
|
Logged
|
|
|
|
|