Show Posts
|
|
Pages: 1 [2] 3 4 ... 6
|
|
16
|
Using Arduino / Programming Questions / Annoying compliler errors
|
on: March 30, 2011, 11:25:19 pm
|
I am getting this error: sketch_mar31a:-1: error: expected ',' or '...' before '&' token sketch_mar31a:-1: error: ISO C++ forbids declaration of 'T' with no type sketch_mar31a:-1: error: 'T' was not declared in this scope sketch_mar31a:-1: error: 'value' was not declared in this scope sketch_mar31a:9: error: 'template<class T> int file_readAnything(T&)' redeclared as different kind of symbol sketch_mar31a:-1: error: previous declaration of 'int file_readAnything'
from this code template <class T> int file_writeAnything(const T& value) { const byte* p = (const byte*)(const void*)&value; int i; for (i = 0; i < sizeof(value); i++) //file.write(*p++); return i; }
template <class T> int file_readAnything(T& value) { byte* p = (byte*)(void*)&value; int i; for (i = 0; i < sizeof(value); i++) // *p++ = file.read(); return i; }
void setup() { }
void loop() { } The above code is a segment from a larger project and it used to work before I upgraded to the latest IDE. Struggleing here. I know there is no code in the setup and loop functions, but it should still complie without any problems. Any ideas?
|
|
|
|
|
17
|
Forum 2005-2010 (read only) / Troubleshooting / Re: Interrupts and stepper motor advice needed.
|
on: March 30, 2010, 09:18:56 am
|
The main problem is that Serial.print(); really isn't up to the job, as it takes way too long to output the data and so it is missing the next 'x' interupts. What you really need to is create an output using the compare A or B register and use an oscilloscope to measure the time bewteen pulses. I understand that most people don't have oscilloscopes lying round; I was lucky enought to inherrit one from my Dad. Try this code: ISR(TIMER1_COMPA_vect) // Timer-1 OC1A Match interrupt handler { //No need to do anything here other than change the pause between pulses // by changing the value of OC1A };
void setup() { Serial.begin(9600); delay(50); TCCR1A = B0011001; TCCR1B = B0100010; TCCR1C = B0000000; TIMSK1 = B0000010; ITFR1 = B0000010; OCR1A = 4000; //Pause between pulses in us OCR1B = 100; //Pulse Length in us TCNT1 = 0; pinMode(10, OUTPUT); //this produces a pulse on pin 10; }
void loop(){}
The way this differs from yours is that it uses phase and frequency correct PWM mode to generate the pulses, rather than 'normal' mode. It also uses the compare 'B' register to output a pulse on pin 10 (you can't change this, as it is hardwired). The length of the pause between pulses is determined by the value of compare register A. In this PWM mode the counter counts both up and down, so a 'top' value of 4000 will result in a total count of 8000 between pulses, at 0.5us per 'tick' that gives you a pause bewteen pulses of 4000us. The great thing about this mode, is that compare register A is double buffered, and updates when the timer reaches 0, making it very easy to control the length of the pulse. You can use the OC1A interrupt vector to change the value of OC1A. The length of the pulse is determined by the value of compare register B, a value of 10 would result in a 10us pulse. If you check the datasheet for your stepper driver it shoudl tell you the minimum pulse length required to induce a step. The 'direction' of the pulse can be changed by changing the value of TCCR1A to B0010001 I hope most (any) of that makes sense. Chris
|
|
|
|
|
18
|
Forum 2005-2010 (read only) / Troubleshooting / Re: Trouble with Servo Jitter on the Mega
|
on: April 19, 2010, 12:52:12 pm
|
|
Ah yes, I see now. Well that will teach me to open mouth before engaging brain won't it.
It states that Servo (the old one) won't work on the mega. I assume this is because of the different timers on the Mega. I would look at the datasheet, but I am at work and I don't think my iPhone will like a 25mb+ PDF!
Thanks for putting me right.
|
|
|
|
|
20
|
Forum 2005-2010 (read only) / Troubleshooting / Re: Trouble with Servo Jitter on the Mega
|
on: April 19, 2010, 07:03:54 am
|
Chris, note that the Servo library supplied with Arduino version 0016 does run one or two servos on timer1 without interrupts I have had a look at the Servo.c file and it look to me like the servo library always uses interrupts to handle the servos, regardless of which timer it is using. If this is not the case, could you point me to the section of code that does this as I am interested in how it decides to use an intrrupt or not. In the mean time I have knocked up some code that will position a servo using timer1 without any interrupts whatsoever. /** * Precision servo positioning. * * Uses timer1 in phase and frequency correct PWM mode * Doesn't use interrupts, so should be immune to interrupt issues. * * Chris Parish 2010 * */
//The standard timings for servos are 1.5ms for center, 1ms and 2ms for the full extents of travel //however, most modern servos can operate an extended range, this can be as wide as 0.5ms to 2.5ms //Consult the documentation for your servo for further details #define SERVO_LOWER_LIMIT 1000 #define SERVO_UPPER_LIMIT 2000 #define SERVO_CENTER 1500
//Set your servo travel here. In standard mode most servos travel approx 90 degrees (45 either side of center) #define SERVO_ANGLE_LOWER 0 #define SERVO_ANGLE_UPPER 90
const int servo = 9; int angle;
void setup() { //Set up the timer------------------------ //TCCR1A register TCCR1A = 0; //clear the register completly TCCR1A |= _BV(COM1A1) | _BV(COM1B1); //set the required bits
//TCCR1B register TCCR1B = 0; //clear the register completley TCCR1B |= _BV(WGM13) | _BV(CS11); //set the required bits
//TCCR1C register TCCR1C = 0; //clear the register completley
//Set the top limit - Complete frame length ICR1 = 20000; //In this mode (assuming that you are running at 16mhz) The values are set in microseconds.
//Set the output compare registers which dictate the servo position OCR1A = SERVO_CENTER; //1.5ms pulse, center the servo OCR1B = SERVO_CENTER; //1.5ms pulse, center the servo
//Set pins 9 and 10 to output the waveform to the servos pinMode(9, OUTPUT); pinMode(10, OUTPUT); Serial.begin(9600);
}
void setServoAngle(int servo, int angle) { //constrain the angle measurement angle = constrain(angle, SERVO_ANGLE_LOWER, SERVO_ANGLE_UPPER); //convert the angle measurement into a pulse length angle = map(angle, SERVO_ANGLE_LOWER, SERVO_ANGLE_UPPER, SERVO_LOWER_LIMIT, SERVO_UPPER_LIMIT);
//write the angle to the appropreate servo output (1 or 2 -aka- 9 or 10) if (servo == 1 || servo == 9) { OCR1A = angle; } else if (servo == 2 || servo == 10) { OCR1B = angle; } }
int getServoAngle(int servo) { int pulse; int angle; if (servo == 1 || servo == 9) { pulse = OCR1A; } else if (servo == 2 || servo == 10) { pulse = OCR1B; } return map(pulse, SERVO_LOWER_LIMIT, SERVO_UPPER_LIMIT, SERVO_ANGLE_LOWER, SERVO_ANGLE_UPPER);
}
There is no loop() in the code above, feel free to out your own in! It does work, I tried it. Chris
|
|
|
|
|
22
|
Forum 2005-2010 (read only) / Troubleshooting / Re: Trouble with Servo Jitter on the Mega
|
on: April 16, 2010, 10:25:05 pm
|
|
Just an idea, and I am perfectly prepared to be shot down in flames here, but would this help?
You said that you are using the servo to control a tracking antenna, so from that I presume that you are using just one servo. Assuming, and it is a big assumption, that none of the other libraries you are using are using timer1, the 16bit timer, you could very easily write a routine to generate the servo PPM train using Phase and Frequency correct PWM mode on the timer in conjunction with the waveform generator to output the pulse train on pins 9 or 10 with a resolution of 1microsecond. this would not require any interrupts and because it is a hardware solution unless something stops the timer for some reason it will continue to run regardless of what the CPU is doing. Basically, if you take the servo handling away from the interrupts then it is not likely to jitter like you have been experiencing.
Chris
|
|
|
|
|
23
|
Forum 2005-2010 (read only) / Troubleshooting / Re: inverting a pwm signal
|
on: March 30, 2010, 11:22:17 am
|
|
I was wondering, I haven't had much experience driving DC motors. I gather that you are using PWM, but how are you controlling speed? is it done by simply increasing the duty cycle, or can it be done by changing the frequency of the pulse, like you would with a stepper motor? Sorry if these are daft questions, but I really don't know anything about DC motors!
Chris
|
|
|
|
|
25
|
Forum 2005-2010 (read only) / Troubleshooting / Re: inverting a pwm signal
|
on: March 30, 2010, 10:38:27 am
|
What i want is to create a pwm signal on pin 10 and it's reverse on pin 11. If you can modify your code to do this i would really appreciate it.
Can I suggest using pins 9 and 10, rather than 10 and 11, because 9 and 10 both run off the same timer, so they should be syncronised. Simply do a normal analogWrite to pin 9, then run my code for pin 10. Like so: void invertAnalogWrite(int pin, int value) { analogWrite(pin, value); TCCR1A = TCCR1A & ~B00110000; //switch off output B TCCR1A |= B00110000; //switch on the B output with inverted output }
void loop() { analogWrite(9, value); invertAnalogWrite(10, value); }
This should do the trick. There is an outside chance that there might be one pluse that is out of sync if the timer ticks between the analogWrite() command and the invert commands. If this would cause a problem, then I would be quite happy to write you some code to get round this. Basically it would require a custom analogWrite function. If that is what you want then tell me and I would happily knock it up. Chris
|
|
|
|
|
26
|
Forum 2005-2010 (read only) / Troubleshooting / Re: inverting a pwm signal
|
on: March 30, 2010, 09:33:56 am
|
As the PMW is managed by the built in timers it sould simply be a matter of changeing the output mode. Lets say you are using PWM on pin 10. This is controlled by the B output of timer 1. So after you set 'analogWrite(10, 100)' you need to reverse the output like this: TCCR1A = TCCR1A & ~B00110000; //switch off output B TCCR1A |= B00110000; //switch on the B output with inverted output
you could combine this into a function like: void invertAnalogWrite(int pin, int value) { analogWrite(pin, value); TCCR1A = TCCR1A & ~B00110000; //switch off output B TCCR1A |= B00110000; //switch on the B output with inverted output }
This would do the job. I have scoped the output and the above does work.
|
|
|
|
|
27
|
Forum 2005-2010 (read only) / Syntax & Programs / Re: Faster interrupts needed
|
on: April 17, 2010, 11:06:26 pm
|
|
Are the LED's being switched on and off, are are you using PWM?
Assuming you are switching on and off First thing I would do would be to work out how long it takes to read from the array and turn the led on and back off again, and then increment the pointer to the next led in the array. Perhaps add a loop to induce a small delay between the on and off commands. Once you know how long the above operation takes you can then calculate the maximum frequency at which you can run the above code. For example, lets say it takes 80microseconds to do everything you want, round it up to 100 to give you some overhead and the maximum frequency is 10kHz. Your previous frequency (assuming a 2ms interrupt) was 500Hz.
Ok, so the next thing I would do would be to use timer2 in CTC mode, with a prescaler of 8 and a top value (set by ORC2A) of 99 (this would give a frequency of 10kHz). Then I would use the timer2 COMPA interrupt to run the above routine.
All the information on the timers can be found in the datasheet for the processor.
Does any of that make sense? It is 5:05 am here and I am very tired.
|
|
|
|
|
29
|
Forum 2005-2010 (read only) / Syntax & Programs / Re: How can I write a custom data structure to EEPROM
|
on: March 27, 2010, 01:39:28 am
|
Is there a possibility the Arduino could lose power while writing the structure to EEPROM? Well yes, but I hope it doesn't. It it looses power it would be because either: I switched it off early, or it died. I hope neither happnes. If it does loose power does that destroy the EEPROM, or just corrupt the data on it? If you decide to use individual structures, I think I see a way for the compiler to automatically determine the offsets. It should be pretty easy for me to work out offsets, that way I can just save the data that has changed since last save. I have now tied it, and it works like a charm. Now all I need to do is build a working menu system, or failing that some kind of serial interface.... Superb. Thanks
|
|
|
|
|
30
|
Forum 2005-2010 (read only) / Syntax & Programs / Re: How can I write a custom data structure to EEPROM
|
on: March 27, 2010, 01:00:45 am
|
|
Hello again Coding Badly,
The structures won't change now, I seem to have got the bugs out of the rest of the code so I don't see any need to change them.
I will take a look at that writeAnything command. If I am interpretting it correctly, I would be able to simply create a master structure containing all the config data, then just write the whole thing to the EEPROM. Is that right?
Chris
|
|
|
|
|