I made a program to detect an inductive loop. Timer 1 works as a PWM, which stores the value of the counter in the ICR1 register when the comparator is triggered. This happens when the voltage on the comparator drops below the reference value of 1.1V. In the interrupt routine, it writes the value from the ICR1 register to the variable t1on. I can see this variable on the serial monitor (serial.println) and it responds nicely to the change in loop inductance. Now we come to the problem: If I want to increment this variable, or any other variable, it only changes by one number from the defined value, or not at all. This applies to the ISR routine and to the main loop. So, I can overwrite a variable, but I can't increment it. Does not help if I change the type of variable(int, uint, byte) Can someone please help me, I've been scratching my head for 3 days?
I noticed that the arduino is running some code of its own in the background because the PWM period doesn't match the UNO frequency and prescaler settings. I also see period changes on the oscilloscope when I use the serial.println command.
Thak you in advance good people
volatile boolean PRINT=0;
volatile boolean start=0;
volatile unsigned int t1on=0;
volatile byte cnt;
volatile byte cnt1;
void setup () {
cli();//disable interrupts
Serial.begin(500000);//enalbel serial comunication
DDRD |= (1<<PD3)| //set pin 3 on port D as autput (bit manipualtion is faster then use digitalwrite,read or bitset )
(1<<PD4); //set pin 4 as output
DDRB |= (1<<PB1)| //UNO set pin 9 on port D as autput (bit manipualtion is faster then use digitalwrite,read or bitset )
(1<<PB2); //set pin D10 as output
DIDR1 |= (1<<AIN0D); // Disable Digital Inputs at AIN0 and AIN1(1 shift left to pin AIN0D - set AIN0D)
//ADCSRA &= ~(1<<ADEN);
//ADCSRB |= (1<<ACME); //Set ACME bit in ADCSRB to use external analog input at AIN1 -ve input
ADMUX = //referenc on AIN0 set to 2,5V
(1<<REFS1) | (1<<REFS0); //votage reference selection 00-Aref; 01-AVcc; 10-reserved; 11-1.1V (ARDUINO UNO-MEGA328p)
ACSR =
(0 << ACD) | // Analog Comparator: Enabled
(1 << ACBG) | // Clear ACBG to use external input to AIN0 +ve input
(1 << ACO) | // Analog Comparator Output: OFF
(1 << ACI) | // Analog Comparator Interrupt Flag: Clear Pending Interrupt by setting the bit
(1 << ACIE) | // Analog Comparator Interrupt: Disabled
(1 << ACIC) | // Analog Comparator Input Capture: 0-Disabled. Postavimo na 1 da omogočimo interrupt na timer 1, zajem stanja timerja v ICR1
(1 << ACIS1) | (0 << ACIS0); // Analog Comparator Interrupt Mode: 00-toggle, 01-reserved, 10-falling, 11-rising
TCCR1A =
(0 << COM1A1) | (0 << COM1A0) | // compare match mode COM1A 00-off, 01-toggle,10-clear on compare match, 11-set on compare match
(1 << COM1B1) | (1 << COM1B0) | // compare match mode COM1B 00-off, 01-toggle,10-clear on compare match, 11-set on compare match
(1 << WGM11) | (1 << WGM10); // select wawe generation mode - look on table in instraction
TCCR1B =
(0 << ICNC1) | // Input capture noice canlcler 1-enable
(1 << ICES1) | // Input capture edge select: 1-positiv edge select
(1<< WGM13) | (1 << WGM12) | // select wawe generation mode - look on table in instraction WGM13 1-non pwm mode
(0 << CS12) | (0 << CS11) |(1 << CS10); // cloclk select, 0- stoped, 1-prescaler 1, 10-prescaler 8...
OCR1A=50000; //top VALUE max 65535
OCR1B=8000; //pwmB SETUP
TIMSK1 =
(1 << ICIE1) | // Input capture INTERRUPT ENABLE
(0 << OCIE1B) | //Output capture B interrupt enable
(0 << OCIE1A) | //Output capture A interrupt enable
(0 << TOIE1); // cloclk select, 0- stoped, 1-prescaler 1, 10-prescaler 8...
sei();//enable interrupts
}
void loop()
{
if (PRINT==1)
{
//cli();
++cnt1;
Serial.println(t1on);
PRINT=0;
}
}
ISR(TIMER1_CAPT_vect)//pozor, za različne procesorje so lahko različni nazivi!
{
cli();
t1on=ICR1;
++cnt;
PRINT=1;
//sei();
}
I have modified this code lots of time, but for instance variable cnt and cnt1 does not increment. Insted of t1on in serial.prinltn I tried with cnt and cnt1, an ther was no incremention.
If I use cnt1=cnt and serial.println(cnt1), then print out on serial monitor continious number 1 printing. the same is for without cnt1=cnt. No mather what variable I put in serial.print line, alway is the answer 1. When i put in serial.println(t1on) it prints the inductiv fitback and is changing the value while aproaching with metal object. I do not understand, why is increment not working. I tried like cnt=cnt+1, ++cnt, cnt++, does not work. Like it would go thrue loop increment from zero and in next loop is set to zero, and again increment to one.
It looks like the variable is reset after each loop and mybe there is no time for background program to update the variable valu from last loop? any other idea?
Why did you change the usage of cli() and sei() again?
Didn't I wrote you how to do it???
Remove cli() and sei() from interrupt completely. Add cli() and sei() around copying your variable in the loop().
Or better yet - just copy my code from post #4 AS IS, without changing anything - and see the result
I'm in transit so just reading the code you posted, thanks.
I don't use all that low level stuff enough to be able to spot your error; have you done anything simpler that could confirm you are setting things up correctly?
Speaking of which, this comment
bit manipualtion is faster then use digitalwrite,read or bitset
is amusing. You do things in a cool but needlessly obscure manner in the setup() function. Which runs once. If ever there were a place to go for clarity over speed, it would be in things done in the setup.
Replace as much as you can of the bit twiddling you do with regular functions. It will increase the ability of ppl to see and focus on what may be the real issues.
If you wrote all that low level stuff, I suggest you be sure you have interpreted the data sheet correctly. If you did not write it, please post the code that you used to create your sketch.
Thak you for your time and help. I have studied atmega data sheets to set registers. Only timer1 works in combination with comparator. I dont think there is a problem in register settings, it works exactley as i want. But i have very litle experience how arduino works in backgraund. I Guess it works on timer 1, so that May be a cause of the problem.
Post a sketch where your register settings "works exactley as [you] want".
Say what it does, and how that is supposed to function in your later sketch. How you needed to change or modify wht worked to fit into the new framework.
It works the same as any microprocessor; do you have experience with any writing ISRs that do stuff in the background and so forth?
Say more about exactly what your end goal is. I am always skeptical of code that uses interrupts, furthermore if it does low level stuff. Interrupts have their place, this may not need to be one of them.
I don't think you timer mode setting of FastPWM to OCR1A is correct.
From the data sheet
The ICR1 Register can only be written when using a Waveform Generation mode that utilizes the ICR1
Register for defining the counter’s TOP value. In these cases the Waveform Generation mode bits
(WGM1[3:0]) must be set before the TOP value can be written to the ICR1 Register.
Based on this, you should be using WGM mode 12 (1100) or 14(1110).
I want fast PWM(pdf line15). I want to set the needed lenght of period(OCR1A) to fit the inductiv response. ICR1 must not be used in PWM settings. It has to be free, that can be used on interrupt event on comparator, whitch trrigers timer1 and then captures current counter value of timer1 in OCR1 register. It is tricky mechanisem that only timer1 in connection with comparator interrupt enables. Comparator is using one input for internal reference 1.1V and on the other input is coil respons which triggers event, when signal falls below 1.1V.