freedomhouse
Newbie level 4
hi,
i want use keypad for dicrete variation of dc motor.
my problem is:
when i hold dow button all work good. (pwm change)
when i relase button stop of work.
i did the on-board debbugger with pickit3 and mplab x....all work good button keep hold and pwm keep hold at the new value, but when i flash the dspic all work but button don't keep hold, when i relase i pwm return to 50%value PDC3 variable.
i don't know why because with on board simulation work and when i program/flash the dspic don't work!!!
I also changed the colums port in all portB...but all is like up, isn't a ports problem.
this is my code.
i want use keypad for dicrete variation of dc motor.
my problem is:
when i hold dow button all work good. (pwm change)
when i relase button stop of work.
i did the on-board debbugger with pickit3 and mplab x....all work good button keep hold and pwm keep hold at the new value, but when i flash the dspic all work but button don't keep hold, when i relase i pwm return to 50%value PDC3 variable.
i don't know why because with on board simulation work and when i program/flash the dspic don't work!!!
I also changed the colums port in all portB...but all is like up, isn't a ports problem.
this is my code.
Code:
#include <p30f2010.h>
#include <libpic30.h>
#include "delays.h"
#define Byte unsigned char
#pragma config FOS=FRC // Oscillator Source (Internal Fast RC)
#define Byte unsigned char
#define stato_mosfet LATFbits.LATF3
#define output_mosfet PORTFbits.RF3
// keypad definitions - LAT for outputs
#define kp_row_1 LATEbits.LATE0
#define kp_row_1_tris TRISEbits.TRISE0
#define kp_row_2 LATEbits.LATE1
#define kp_row_2_tris TRISEbits.TRISE1
#define kp_row_3 LATEbits.LATE2
#define kp_row_3_tris TRISEbits.TRISE2
#define kp_row_4 LATEbits.LATE3
#define kp_row_4_tris TRISEbits.TRISE3
// keypad definitions - PORT for inputs - be sure to us CNxx pins for input!
#define kp_col_1 PORTCbits.RC13
#define kp_col_1_tris TRISCbits.TRISC13
#define kp_col_2 PORTCbits.RC14
#define kp_col_2_tris TRISCbits.TRISC14
#define kp_col_3 PORTDbits.RD1
#define kp_col_3_tris TRISDbits.TRISD1
#define kp_col_4 PORTFbits.RF2
#define kp_col_4_tris TRISFbits.TRISF2
int key=0; // return value
int saved_key = 0;
int G; // gradi ogni movimento 360/N
int U; //tasti inutilizzati
int N; //numero slot
int Max_count_giro; //n linee contate a giro
float Risoluzione; // risoluzione encoder
int Pos_misurata; //posiizione angolare
int Pos_desiderata; //posiizione desiderata variata con Vrif
long Error[10];
long Accumulator;
long PID;
int PTerm;
int ITerm;
int DTerm;
int i;
Byte Divider;
int ADCValue;
int keypad(void);
void InitADC(void);
void InitPWM(void);
void InitQEI(void);
void Calcolo_Posizione(void);
void Calcolo_Pos_desiderata(void);
void OverHeat(void);
int main(void); // Declare Main Function
int main(void)
{ TRISF=0x0001;
stato_mosfet=1;//chiudo mosfet
// Set constants here
PTerm =2000;
ITerm =25;
DTerm = 0;
Divider =10;
N=10;
G=360/N;
InitADC();
InitPWM();
InitQEI();
/* Set up the Interrupts */
while(1)
{
key=keypad();
if (key!=0)
{
saved_key = key;
}
Pos_desiderata=saved_key*G*(32767/360);
Pos_misurata=POSCNT*32767/1999; // misura posizone angolare riportare 1999 linee a numero digitale 16bit-->
//---> risoluzione*posizione in linee misurata/max_count_giro=POSCNT/32767
Byte i=0;
for(i=0;i<10;i++)
Error[i+1] = Error[i];
Error[0] = Pos_desiderata-Pos_misurata;
PID = Error[0]*PTerm; // start with proportional gain
Accumulator += Error[0]; // accumulator is sum of errors
PID += ITerm*Accumulator; // add integral gain and error accumulation
PID += DTerm*(Error[0]-Error[9]); // differential gain comes next
PID = PID>>Divider; // scale PID down with divider
if (Accumulator > 40000)
Accumulator = 40000;
if (Accumulator < -40000)
Accumulator = -40000;
//comment out to speed up PID loop
//Serial.print("PID= ");
// Serial.println(PID,DEC);
// limit the PID to the resolution we have for the PWM variable
if(PID>=121)
PID = 100;
if(PID<=-121)
PID =-100;
PDC3=PID+PTPER;
OverHeat();
}
return 0;
}
void InitPWM(void)
{
// ***** CONFIGURE 3 OUTPUT PWM *****
PTPER = 0x007A; // 122 Time base register = 126d (=> PDCx Value for 100% Duty Cycle = 254d (2X(PTPER+1)) )
PDC3 = PTPER; // PWM1 value = 50%
//PWMCON1 = 0x0077; // PMOD3:PMOD1 = 0 (PWM I/O pin pairs are in the complementary output mode)
// PEN3H-PEN1H = 7 (PWM1H..PWM3H pins are enabled for PWM output)
// PEN3L-PEN1L = 7 (PWM1L..PWM3L pins are enabled for PWM output)
PWMCON1=0x0044; //complementary mode, only PWM3H & pwm3l as PWM outpur
PWMCON2 = 0x0004; // SEVOPS<3:0> = 0 (PWM Special Event Trigger Output Postscale Select bits = 1:1 (Not Used))
// IUE = 1 (Updates to the active PDC registers are immediate)
// OSYNC = 0 (Output overrides via the OVDCON register occur on next TCY boundary)
// UDIS = 0 (Updates from duty cycle and period buffer registers are enabled)
//PTCON = 0x800C; // PTEN = 1 (PWM time base is ON)
// PTSIDL = 0 (PWM time base runs in CPU Idle mode)
// PTOPS<3:0> = 0 (PWM Time Base Output Postscale Select bits = 1:1 Postscale)
// PTCKPS<1:0> = 3 (PWM Time Base Input Clock Prescale Select bits => clock period is 64 TCY (1:64 prescale))
// PTMOD<1:0> = 0 (PWM Time Base Mode Select bits => PWM time base operates in a free running mode)
// If internal 7.37 MHz oscillator is used =>
// PWM Frequency = FOSC/(4*PTMRPrescaler*(PTPER+1))
// PWM Frequency = 7.37e6/(4*64*(126+1) = 226.7 Hz
// PWM Duty Cycle [%] = 100*(2*PDCx)/(PTPER+1)
PTCON=0x8000; // 1:1prescale PTPER=(FOSC/(4*PTMRRrescaler*PWM Frequency))-1=
// PTPER= (7.37e6/4*1*15e3)-1)=122
DTCON1= 0x0008; // deadtime=DTCON1value*Tcy = 2us
}
void InitADC(void)
{ // ***** CONFIGURE 3 INPUT ADC *****
ADPCFG = 0x0030; // PCFG<15:0>: Analog Input Pin Configuration Control bits
// 1 = Analog input pin in Digital mode, port read input enabled, A/D input multiplexer input connected to AVSS
// 00 = Analog input pin in Analog mode, port read input disabled, A/D samples pin voltage
// RB4..RB5 = digital QEI
ADCON1 = 0x00EC; // ADON: A/D Operating Mode bit = 0 (A/D Converter is off)
// ADSIDL : Stop in idle mode bit = 0 (Continue module operation in idle mode)
// FORM<1:0> : Data Output Format bits = 0 (Integer 10 bits)
// SSRC<2:0>: Conversion Trigger Source Select bits = 7 (Internal counter ends sampling and starts conversion (auto convert))
// SIMSAM bit : Simultaneous Sample Select bit = 1 implies ...
// Samples CH0, CH1, CH2, CH3 simultaneously (when CHPS = 1x)
// or
// Samples CH0 and CH1 simultaneously (when CHPS = 01)
// ASAM : A/D Sample Auto-Start bit = 1 (for auto sample after convert)
ADCON2 = 0xE308; // VCFG<2:0> : Voltage Reference Configuration Configuration bits = 7 (Reference Voltages = AVdd/AVss)
// CSCNA bit : Scan Input Selections for CH0+ S/H Input for MUX A Input Multiplexer Setting bit = 0 (Do Not Scan inputs)
// CHPS<1:0> : Selects Channels Utilized bits = 1x implies simultaneous ...
// sample CH0 to CH3
// SMPI<3:0> : Sample/Convert Sequences Per Interrupt Selection bits = 2 for interrupt after 3 converts
// BUFM : Buffer Mode Select bit = 0 (Buffer configured as one 16-word buffer ADCBUF(15...0.))
// ALTS: Alternate Input Sample Mode Select bit = 0 (Always use MUX A input multiplexer settings)
ADCON3 = 0x0302; // SAMC<4:0>: Auto-Sample Time bits = 3 (3 Tad)
// ADRC: A/D Conversion Clock Source bit = 0 (Clock derived from system clock)
// ADCS<5:0>: A/D Conversion Clock Select bits = 2 (2 TCY)
ADCHS = 0x0020; // CH123NA<1:0>: Channel 1, 2, 3 Negative Input Select for MUX A Multiplexer Setting bits = 0 (CH1, CH2, CH3 negative input is VREF-)
// CH123SA: Channel 1, 2, 3 Positive Input Select for MUX A Multiplexer Setting bit = 1 implies...
// CH1 = AN3 / CH2 = AN4 / CH3 = AN5
// ADCBUF1 = AN3 / ADCBUF2 = AN4 / ADCBUF3 = AN5
// CH0NA: Channel 0 Negative Input Select for MUX A Multiplexer Setting bit = 0 (Channel 0 negative input is VREF-)
// CH0SA<3:0>: Channel 0 Positive Input Select for MUX A Multiplexer Setting bits = 0 implies...
// Connect AN0 as CH0 input => ADCBUF0 = AN0
ADCSSL = 0; // CSSL<15:0>: A/D Input Pin Scan Selection bits
// 1 = Select ANx for input scan
// 0 = Skip ANx for input scan
// ***NOT USED***
ADCON1bits.ADON = 1; // turn ADC ON
}
void InitQEI(void)
{
/// INITIALIZING THE QEI MODULE
QEICONbits.QEIM = 0; // Disable QEI Module
QEICONbits.CNTERR = 0; // Clear any count errors
QEICONbits.QEISIDL = 0; // Continue operation during sleep
QEICONbits.SWPAB = 0; // QEA and QEB not swapped
QEICONbits.PCDOUT = 0; // Normal I/O pin operation
QEICONbits.POSRES = 1; // Index pulse resets position counter POSRES=0 if QEIM=111 reset by MAXCNT
DFLTCONbits.CEID = 1; // Count error interrupts disabled
DFLTCONbits.QEOUT = 1; // Digital filters output enabled for QEn pins
DFLTCONbits.QECK = 5; // 1:64 clock divide for digital filter for QEn
//DFLTCONbits.INDOUT = 1; // Digital filter output enabled for Index pin
//DFLTCONbits.INDCK = 5; // 1:64 clock divide for digital filter for Index
POSCNT = 0; // Reset position counter
QEICONbits.QEIM = 6; // X4 mode with position counter reset by Index or QEIM=111 position reset MAXCNT if 3rd pin encoder INDEX is not present
}
void OverHeat (void)
{
ADCValue=ADCBUF0;
if(ADCValue>429) //4.5V max input if T>70°C stoppa alimentazione dspi
{stato_mosfet=0;} // else if<=50°C riprendi l'alimentazione dspic
else if(ADCValue<=307) //ADCBUF3 an2
{stato_mosfet=1;}
}
// read 4x4 keypad
int keypad(void)
{
kp_row_1_tris = 1; // rows are outputs
kp_row_2_tris = 1; // rows are outputs
kp_row_3_tris = 1; // rows are outputs
kp_row_4_tris = 1; // rows are outputs
kp_col_1_tris = 1; // columns are inputs
kp_col_2_tris = 1; // columns are inputs
kp_col_3_tris = 1; // columns are inputs
kp_col_4_tris = 1; // columns are inputs
kp_row_1_tris = 0; // rows are outputs
kp_row_1 = 0; // row 1 low to select
kp_row_2 = 1;
kp_row_3 = 1;
kp_row_4 = 1;
delayms(10); // allow settle time
if(!kp_col_1)
{
key = 1;
}
if(!kp_col_2)
{
key = 2;
}
if(!kp_col_3)
{
key = 3;
}
if(!kp_col_4)
{
key = 0;
}
kp_row_2_tris = 0; // rows are outputs
kp_row_1 = 1;
kp_row_2 = 0; // row 2 low to select
kp_row_3 = 1;
kp_row_4 = 1;
delayms(10); // allow settle time
if(!kp_col_1)
{
key = 4;
}
if(!kp_col_2)
{
key = 5;
}
if(!kp_col_3)
{
key = 6;
}
kp_row_3_tris = 0; // rows are outputs
kp_row_1 = 1;
kp_row_2 = 1;
kp_row_3 = 0; // row 3 low to select
kp_row_4 = 1;
delayms(10); // allow settle time
if(!kp_col_1)
{
key = 7;
}
if(!kp_col_2)
{
key = 8;
}
if(!kp_col_3)
{
key = 9;
}
kp_row_4_tris = 0; // rows are outputs
kp_row_1 = 1;
kp_row_2 = 1;
kp_row_3 = 1;
kp_row_4 = 0; // row 4 low to select
delayms(10); // allow settle time
if(!kp_col_2)
{
key = 10;
}
return key; // return
}