Hello guys!
I'm trying to use an Arduino Due to control a 3-phase inverter (used to drive permanent magnet ac motor) and a buck converter. For this task I will need to read at least 6 current measurements, some voltage levels and 3 pulse trains from an encoder. I also need to send out 5 PWM signals. I have managed to read the encoder pulses and send out PWM.
The problem at hand is now to read the analog inputs, fast and accurate enough. I tried with the analogRead, but this can only run 10000 sps, which is not near fast enough. I scanned this forum in search for help and found something similar to what I need (http://arduino.cc/forum/index.php/topic,137635.15.html). I tried this at the lab, and the result wasnt to good. The sampled data was very noisy, and didnt read what I expected.
I want to read the analog inputs with 150kHz freq (the current measures at least). Some analog inputs can be read slower. Any ideas how to solve this problem? Thanks in advance
#include <Encoder.h>
// Black magic
void startTimer(Tc *tc, uint32_t channel, IRQn_Type irq, uint32_t frequency) {
pmc_set_writeprotect(false);
pmc_enable_periph_clk((uint32_t)irq);
TC_Configure(tc, channel, TC_CMR_WAVE | TC_CMR_WAVSEL_UP_RC | TC_CMR_TCCLKS_TIMER_CLOCK4);
uint32_t rc = VARIANT_MCK/128/frequency; //128 because we selected TIMER_CLOCK4 above
TC_SetRA(tc, channel, rc/2); //50% high, 50% low
TC_SetRC(tc, channel, rc);
TC_Start(tc, channel);
tc->TC_CHANNEL[channel].TC_IER=TC_IER_CPCS;
tc->TC_CHANNEL[channel].TC_IDR=~TC_IER_CPCS;
NVIC_EnableIRQ(irq);
}
//assigning pins to variables and declaring encoder
int aPin=57;
int bPin=58;
int cPin=59;
int vfcPin=55;
int ibuckPin=62;
int ipmsmPin=60;
int iscPin=61;
int pwmbuckPin=3;
int pwmaPin=5;
int pwmbPin=6;
int pwmcPin=7;
int enablebuckPin=50;//not assigned on the physical board yet
int encA=26;
int encB=24;
int encZ=22;
int pwmfcPin=2;
volatile long a=0;
volatile long b=0;
volatile long c=0;
volatile long oldPos= -999;
volatile long newPos= 0;
volatile int enablebuck=0;
volatile long da=0;
volatile long db=0;
volatile long dc=0;
volatile long dbuck=0;
volatile long ibuck=0;
volatile long iboost=0;
//setup:
//*Assigning pins as either input or output
//*starting timers
void setup(){
//setting up serial communication to computer, for testing purposes only
Serial.begin(9600);
Serial.println("Motor encoder test:");
pinMode(aPin,INPUT);
pinMode(bPin,INPUT);
pinMode(cPin,INPUT);
pinMode(vfcPin,INPUT);
pinMode(pwmaPin,OUTPUT);
pinMode(pwmbPin,OUTPUT);
pinMode(pwmcPin,OUTPUT);
pinMode(enablebuckPin,OUTPUT);
pinMode(pwmbuckPin,OUTPUT);
pinMode(ipmsmPin,INPUT);
pinMode(ibuckPin,INPUT);
pinMode(encZ,INPUT);
attachInterrupt(encZ,reset,RISING);
ADC->ADC_MR |= 0x80; //set ADC in free running mode
ADC->ADC_CR=2; //enable ADC clock
ADC->ADC_CHER=0x1FF; //enable A0->A7+A8
// Start timer. Parameters are:
// TC1 : timer counter. Can be TC0, TC1 or TC2
// 0 : channel. Can be 0, 1 or 2
// TC3_IRQn: irq number. See table.
// 50000 : frequency (in Hz)
// The interrupt service routine is TC3_Handler. See table.
startTimer(TC1, 0, TC3_IRQn, 25000);//timer for, pwm write inverter and sync buck
startTimer(TC1, 1, TC4_IRQn, 50000); //timer for reading analog inputs
startTimer(TC1, 2, TC5_IRQn, 2);
// Paramters table:
// TC0, 0, TC0_IRQn => TC0_Handler()
// TC0, 1, TC1_IRQn => TC1_Handler()
// TC0, 2, TC2_IRQn => TC2_Handler()
// TC1, 0, TC3_IRQn => TC3_Handler()
// TC1, 1, TC4_IRQn => TC4_Handler()
// TC1, 2, TC5_IRQn => TC5_Handler()
// TC2, 0, TC6_IRQn => TC6_Handler()
// TC2, 1, TC7_IRQn => TC7_Handler()
// TC2, 2, TC8_IRQn => TC8_Handler()
}
Encoder myEnc(encA,encB);
void loop(){
newPos = myEnc.read();
if (newPos != oldPos){
oldPos=newPos;
//writes to the serial port, for testing purposes only
Serial.println(newPos);
}
}
// This interrupt routine is:
//*writing duty cycles to the sync. buck gate drivers
//*writing duty cycles to the inverter gate drivers
void TC3_Handler()
{
// You must do TC_GetStatus to "accept" interrupt
// As parameters use the first two parameters used in startTimer (TC1, 0 in this case)
TC_GetStatus(TC1, 0);
//writing duty cycles to the inverterboard
analogWrite(pwmaPin,251);//replace 128 with the calculated values da
analogWrite(pwmbPin,128);//replace 128 with the calculated values db
analogWrite(pwmcPin,0);//replace 128 with the calculated values dc
analogWrite(pwmbuckPin,200);
analogWrite(pwmfcPin,32);
}
//This interrupt routine is:
//*reading currents from inverter (3 readings)
void TC4_Handler()
{
TC_GetStatus(TC1,1);
//a=analogRead(aPin);
//b=analogRead(bPin);
//c=analogRead(cPin);
while((ADC->ADC_ISR & 0x1FF)!=0x1FF);
a=ADC->ADC_CDR[4]; //read data on A3 pin
b=ADC->ADC_CDR[3]; //read data on A4 pin
c=ADC->ADC_CDR[2]; //read data on A5 pin
}
void TC5_Handler()
{
TC_GetStatus(TC1,2);
}
void reset(){
myEnc.write(0);
newPos=0;
oldPos=0;
}