Здравствуйте, возникла проблема. Делаю классического робота, который будет ездить по комнате и обнаруживать препятствия при помощи известного УЗ-датчика. Но решил добавить ему ещё и воспроизведение звука, всего одну фразу. Звук воспроизводится не с карты памяти, а с отдельного файла. Проблема в том, что при воспроизведении звука один из моторов перестаёт крутиться, если скорость для него указана ниже 255. Без этого всё работает как надо, скорость настраивается в коде без проблем, но как только в коде появляется команда воспроизведения звука всё сразу перестаёт работать. Моторы подключены через драйвер MX1508, один к выводам D6 и D5, второй, с которым и возникают проблемы, к D9 и D10. Динамик подключен через усилитель PAM8403 к пину D11. Вот код:
Вот эти функции отвечают за воспроизведение звука:
C++:
#include <stdint.h>
#include <avr/interrupt.h>
#include <avr/io.h>
#include <avr/pgmspace.h>
#include "sounddata.h"
#define SAMPLE_RATE 8000 // скорость воспроизведения
const int PinB1 = 10;
const int PinB2 = 9;
const int PinA1 = 6;
const int PinA2 = 5;
int trigPin = 8;
int echoPin = 7;
long duration, distance;
#define LEFT_SENSOR_PIN A3
#define RIGHT_SENSOR_PIN A4
int MaxSpdR = 105;
int MaxSpdL = 82;
#define SLOW_SPEED 35
#define BACK_SLOW_SPEED 30
#define BACK_FAST_SPEED 50
#define BRAKE_K 4
#define STATE_FORWARD 0
#define STATE_RIGHT 1
#define STATE_LEFT 2
#define SPEED_STEP 2
#define FAST_TIME_THRESHOLD 500
#define SPEED 85
int state = STATE_FORWARD;
int currentSpeed = SPEED;
int fastTime = 0;
unsigned long timing;
unsigned long timingn;
unsigned long timingf;
int detectState1 = 0;
int detectState2 = 0;
int speakerPin = 11;
volatile uint16_t sample;
byte lastSample;
unsigned long timing1; // Переменная для хранения точки отсчета воспроизведения звука
ISR(TIMER1_COMPA_vect) {
if (sample >= sounddata_length) {
if (sample == sounddata_length + lastSample) {
stopPlayback();
} else {
// Рампа вниз до нуля, чтобы уменьшить щелчок в конце воспроизведения.
OCR2A = sounddata_length + lastSample - sample;
}
} else {
OCR2A = pgm_read_byte(&sounddata_data[sample]);
}
++sample;
}
void startPlayback() {
pinMode(speakerPin, OUTPUT);
ASSR &= ~(_BV(EXCLK) | _BV(AS2));
TCCR2A |= _BV(WGM21) | _BV(WGM20);
TCCR2B &= ~_BV(WGM22);
TCCR2A = (TCCR2A | _BV(COM2A1)) & ~_BV(COM2A0);
TCCR2A &= ~(_BV(COM2B1) | _BV(COM2B0));
TCCR2B = (TCCR2B & ~(_BV(CS12) | _BV(CS11))) | _BV(CS10);
OCR2A = pgm_read_byte(&sounddata_data[0]);
cli();
TCCR1B = (TCCR1B & ~_BV(WGM13)) | _BV(WGM12);
TCCR1A = TCCR1A & ~(_BV(WGM11) | _BV(WGM10));
TCCR1B = (TCCR1B & ~(_BV(CS12) | _BV(CS11))) | _BV(CS10);
OCR1A = F_CPU / SAMPLE_RATE; // 16e6 / 8000 = 2000
TIMSK1 |= _BV(OCIE1A);
lastSample = pgm_read_byte(&sounddata_data[sounddata_length - 1]);
sample = 0;
sei();
}
void stopPlayback() {
TIMSK1 &= ~_BV(OCIE1A);
TCCR1B &= ~_BV(CS10);
TCCR2B &= ~_BV(CS10);
digitalWrite(speakerPin, LOW);
}
void runForward()
{
state = STATE_FORWARD;
fastTime += 1;
if (fastTime < FAST_TIME_THRESHOLD) {
currentSpeed = SLOW_SPEED;
} else {
currentSpeed = min(currentSpeed + SPEED_STEP, SPEED);
}
analogWrite(PinA1, 0);
analogWrite(PinA2, currentSpeed);
analogWrite(PinB1, currentSpeed);
analogWrite(PinB2, 0);
}
void steerRight()
{
state = STATE_RIGHT;
fastTime = 0;
analogWrite(PinA1, 0);
analogWrite(PinA2, 0);
analogWrite(PinB1, SPEED);
analogWrite(PinB2, 0);
}
void steerLeft()
{
state = STATE_LEFT;
fastTime = 0;
analogWrite(PinA1, 0);
analogWrite(PinA2, SPEED);
analogWrite(PinB1, 0);
analogWrite(PinB2, 0);
}
void stepBack(int duration, int state) {
if (!duration)
return;
int leftSpeed = (state == STATE_RIGHT) ? BACK_SLOW_SPEED : BACK_FAST_SPEED;
int rightSpeed = (state == STATE_LEFT) ? BACK_SLOW_SPEED : BACK_FAST_SPEED;
analogWrite(PinA1, rightSpeed);
analogWrite(PinA2, 0);
analogWrite(PinB1, 0);
analogWrite(PinB2, leftSpeed);
delay(duration);
}
void runRight() {
analogWrite(PinA1, MaxSpdR);
analogWrite(PinA2, 0);
analogWrite(PinB1, MaxSpdL);
analogWrite(PinB2, 0);
}
void runLeft() {
analogWrite(PinA1, 0);
analogWrite(PinA2, MaxSpdR);
analogWrite(PinB1, 0);
analogWrite(PinB2, MaxSpdL);
}
void runBack() {
analogWrite(PinA1, MaxSpdR);
analogWrite(PinA2, 0);
analogWrite(PinB1, 0);
analogWrite(PinB2, MaxSpdL);
}
void runForward1() {
analogWrite(PinA1, 0);
analogWrite(PinA2, MaxSpdR);
analogWrite(PinB1, MaxSpdL);
analogWrite(PinB2, 0);
}
void stopp() {
analogWrite(PinA1, 0);
analogWrite(PinA2, 0);
analogWrite(PinB1, 0);
analogWrite(PinB2, 0);
}
void setup() {
pinMode(13, INPUT_PULLUP);
pinMode(PinA1, OUTPUT);
pinMode(PinA2, OUTPUT);
pinMode(PinB1, OUTPUT);
pinMode(PinB2, OUTPUT);
pinMode(trigPin, OUTPUT);
pinMode(echoPin, INPUT);
Serial.begin(9600);
startPlayback();
}
void loop() {
while (digitalRead(13)) {
if (millis() - timing > 5) {
digitalWrite(trigPin, LOW);
delayMicroseconds(2);
digitalWrite(trigPin, HIGH);
delayMicroseconds(10);
duration = pulseIn(echoPin, HIGH);
distance = duration / 58.2;
timing = millis();
}
if (millis() - timingn > 4000) {
// startPlayback();
timingn = millis();
}
if (distance > 27) {
runForward1();
}
else {
stopp();
delay(1000);
runBack();
delay(500);
stopp();
delay(800);
runLeft();
delay(220);
}
}
stopp();
delay(3000);
while (digitalRead(13) == 0) {
boolean left = digitalRead(LEFT_SENSOR_PIN);
boolean right = !digitalRead(RIGHT_SENSOR_PIN);
int targetState;
if (left == right) {
targetState = STATE_FORWARD;
} else if (left) {
targetState = STATE_LEFT;
} else {
targetState = STATE_RIGHT;
}
if (state == STATE_FORWARD && targetState != STATE_FORWARD) {
int brakeTime = (currentSpeed > SLOW_SPEED) ?
currentSpeed : 0;
stepBack(brakeTime, targetState);
}
switch (targetState) {
case STATE_FORWARD:
runForward();
break;
case STATE_RIGHT:
steerRight();
break;
case STATE_LEFT:
steerLeft();
break;
}
}
}
C++:
SR(TIMER1_COMPA_vect) {
if (sample >= sounddata_length) {
if (sample == sounddata_length + lastSample) {
stopPlayback();
} else {
// Рампа вниз до нуля, чтобы уменьшить щелчок в конце воспроизведения.
OCR2A = sounddata_length + lastSample - sample;
}
} else {
OCR2A = pgm_read_byte(&sounddata_data[sample]);
}
++sample;
}
void startPlayback() {
pinMode(speakerPin, OUTPUT);
ASSR &= ~(_BV(EXCLK) | _BV(AS2));
TCCR2A |= _BV(WGM21) | _BV(WGM20);
TCCR2B &= ~_BV(WGM22);
TCCR2A = (TCCR2A | _BV(COM2A1)) & ~_BV(COM2A0);
TCCR2A &= ~(_BV(COM2B1) | _BV(COM2B0));
TCCR2B = (TCCR2B & ~(_BV(CS12) | _BV(CS11))) | _BV(CS10);
OCR2A = pgm_read_byte(&sounddata_data[0]);
cli();
TCCR1B = (TCCR1B & ~_BV(WGM13)) | _BV(WGM12);
TCCR1A = TCCR1A & ~(_BV(WGM11) | _BV(WGM10));
TCCR1B = (TCCR1B & ~(_BV(CS12) | _BV(CS11))) | _BV(CS10);
OCR1A = F_CPU / SAMPLE_RATE; // 16e6 / 8000 = 2000
TIMSK1 |= _BV(OCIE1A);
lastSample = pgm_read_byte(&sounddata_data[sounddata_length - 1]);
sample = 0;
sei();
}
void stopPlayback() {
TIMSK1 &= ~_BV(OCIE1A);
TCCR1B &= ~_BV(CS10);
TCCR2B &= ~_BV(CS10);
digitalWrite(speakerPin, LOW);
}