С помощью:
Код:
#include "FreeRTOS_AVR.h"#include "basic_io_avr.h"
/***
* HITEC servo ranges from 0.9 to 2.4 ms
* values in usec
***/
const int firstPulse = 0.7 * 1000;
const int centerPulse = 1.5 * 1000;
const int lastPulse = 2.4 * 1000;
const int cycleLength = 20 * 1000;
const int degree = (lastPulse - firstPulse) / 180 * 1.0; //9.44
const int SERVO_PIN = 29;
const int ULTRASOON_PIN = 43;
void servoTask(void* p);
void ultrasoonTask(void* p);
void receiveTask(void* p);
QueueHandle_t xQueueDistance, xQueueDegrees;
void setup() {
// put your setup code here, to run once:
cli();
USART_init();
Timer2_init();
Timer3_init();
sei();
pinMode(SERVO_PIN, OUTPUT);
xQueueDistance = xQueueCreate(1, sizeof(uint8_t));
xQueueDegrees = xQueueCreate(1, sizeof(int));
xTaskCreate(servoTask, "Servo task", 200, NULL, 1, NULL);
xTaskCreate(ultrasoonTask, "Ultrasoon task", 200, NULL, 1, NULL);
xTaskCreate(receiveTask, "Receive task", 200, NULL, 1, NULL);
vTaskStartScheduler();
while(1) {writeString("DEAD LOOP\n");};
}
volatile int pulse=0;
ISR (TIMER2_COMPA_vect) {
static int x=0;
x++;
if(x%2) {
//vPrintStringAndNumber("ServoPos= ", pulse);
//moveServo(pulse);
}
}
ISR( TIMER3_COMPA_vect){}
void ultrasoonTask(void* p) {
uint8_t ultrasoonValue;
portBASE_TYPE xStatus;
while(1) {
ultrasoonValue = ping();
//vPrintStringAndNumber("Ping= ", ultrasoonValue);
xQueueSendToBack(xQueueDistance, &ultrasoonValue, 0);
vTaskDelay(500 / portTICK_PERIOD_MS);
}
}
void servoTask(void *p) {
uint8_t inValue;
int m_degrees;
portBASE_TYPE xStatus;
while(1) {
xStatus = xQueueReceive(xQueueDistance, &inValue, 0);
if(xStatus == pdPASS) {
//vPrintStringAndNumber("ServoRead= ", inValue);
m_degrees = changeServoPosition((int)inValue);
//vPrintStringAndNumber("ServoPos= ", m_degrees);
xQueueSendToBack(xQueueDegrees, &m_degrees, 0);
}
vTaskDelay(500 / portTICK_PERIOD_MS);
}
}
void receiveTask(void* p) {
int m_degrees;
portBASE_TYPE xStatus;
while(1) {
xStatus = xQueueReceive(xQueueDegrees, &m_degrees, 0);
if(xStatus == pdPASS) {
//vPrintStringAndNumber("ServoPos= ", m_degrees);
pulse = m_degrees;
//vPrintStringAndNumber("ServoPos= ", pulse);
}
vTaskDelay(500 / portTICK_PERIOD_MS);
}
}
long ping() {
pinMode(ULTRASOON_PIN, OUTPUT); // Switch signalpin to output
digitalWrite(ULTRASOON_PIN, LOW); // Send low pulse
delayMicroseconds(2); // Wait for 2 microseconds
digitalWrite(ULTRASOON_PIN, HIGH); // Send high pulse
delayMicroseconds(5); // Wait for 5 microseconds
digitalWrite(ULTRASOON_PIN, LOW); // Holdoff
pinMode(ULTRASOON_PIN, INPUT); // Switch signalpin to input
digitalWrite(ULTRASOON_PIN, HIGH); // Turn on pullup resistor
long temp = pulseIn(ULTRASOON_PIN, HIGH); //Listen for echo
//convert to CM: sound speed is 340 m/s. 29microseconds/cm.
// ping signal travels out and back, take half distance travelled.
return temp / 29 / 2;
}
void moveServo(int p) {
digitalWrite(SERVO_PIN, HIGH);
delayMicroseconds(p);
digitalWrite(SERVO_PIN, LOW);
delayMicroseconds(cycleLength - p);
}
int changeServoPosition(int in) {
int p = in * degree + firstPulse;
if(p < firstPulse) {
p = firstPulse;
} else if(p > lastPulse) {
p = lastPulse;
}
return p;
}
void Timer2_init() {
TCCR2A = 0;
TCCR2B = 0;
// CTC Mode
TCCR2B |= (1<<WGM22);
//
// Prescaler mode: 1024
TCCR2B |= (1<<CS22) | (1<<CS20);
TIMSK2 = (1<<OCIE2A); //interrupt enable
TCNT2 = 0;
OCR2A = 156;
}
/**
* Timer3 is 16 bits, max tellen tot 2^16= 65535
* OCR3A = FCPU / prescaler / frequentie
* FCPU = 16000000, Prescaler = 1024, FCPU/Prescaler = 15625
* Frequentie = 1/(time in seconds), 20ms = 0.02s, 1/s = 50Hz
* OCR3A = 312.5
**/
void Timer3_init() {
TCCR3A = 0;
TCCR3B = 0;
// CTC Mode
TCCR3B |= (1<<WGM32);
// Prescaler mode: 1024
TCCR3B |= (1<<CS32) | (1<<CS30);
TIMSK3 = (1<<OCIE3A); //interrupt enable
TCNT3 = 0;
OCR3A = 313;
}
void USART_init() {
/* Set baud rate */
UBRR0H = 0;//UBRR0H = (unsigned char)(ubrr>>8);
UBRR0L = 16000000/16/9600-1; //FCPU en BAUD. UBRR0L = (unsigned char)ubrr;
UCSR0A = 0;
/* Enable receiver and transmitter */
UCSR0B = (1<<RXEN0)|(1<<TXEN0);
/* Set frame format: 8data, 2stop bit */
UCSR0C = (1<<USBS0)|(3<<UCSZ00); // URSEL: Register select, om op UCSRC te schrijven
// USBS: op 2stop bit zetten
// UCSZ0: 3 erop schuiven, hierdoor UCSZ0 en UCSZ1 op 1 geset. 8 bit
}
void writeChar(char data){
/* Wait for empty transmit buffer */
while ( !( UCSR0A & (1<<UDRE0)) ); // UDRE is een flag die wacht totdat data in de buffer gezet mag worden.
/* Put data into buffer, sends the data */
UDR0 = (uint8_t)data;
}
void writeString(char* str){
while(*str)
writeChar(*str++);
}
void writeInteger(int16_t number, uint8_t base){
char nmb[3];
itoa(number, nmb, base);
writeString(nmb);
}
char readChar(){
/* Wait for data to be received */
while ( !(UCSR0A & (1<<RXC0)) ); // RXC is een flag die wacht totdat er data bij de buffer van de ontvanger is.
/* Get and return received data from buffer */
return (char)UDR0;
}
void loop(){
}
Проблема:
volatile int pulse
это глобальная переменная, которую я хочу использовать в ISR Timer2.
С receiveTask
Я получаю значение из очереди и устанавливаю его в качестве значения импульса.
Но каждый раз значение пульса равно 0.
То, как вы используете xQueueReceive () Функция выглядит корректно, поэтому при условии, что тест if (xStatus == pdPASS) действительно проходит, я предполагаю, что проблема на самом деле в том, где вы отправляете значение в очередь, а не в том месте, где вы его получаете. Вы не показываете этот код, хотя. Вы уверены, что действительно пишете в очередь, и что значение, записываемое в очередь, не всегда равно 0?