Отключение i2c после нескольких прерываний.
- Войдите на сайт для отправки комментариев
Пнд, 13/06/2016 - 20:22
Здравствуйте уважаемые форумчане.
По прерыванию я считаю импульсы, потом количество импульсов по таймеру сбрасываю, импульсы насчитанные за секунду передаю по i2c (вместе с еще парой тестовых параметров). Вместе с этим генерируется ШИМ . Сначала от внешнего устройства приходит число 7, ардуинка начинает генерировать ШИМ и посылать на устройство насчитанное кол-во импульсов и еще некоторые тестовые данные. По непонятной мне причине спустя 5-6 пересылок i2c перестает принимать и получать данные. Почему?
#include <Wire.h>
#include <TimerOne.h>
#define SLAVE_ADDRESS 0x04
int mode = 0;
int pwd_freq=0;
int ledPin = 13;
int writePWMpin = 9;
unsigned int onSecondImpulsCounter=0,onSecondImpulsSend=0;
void setup() {
pinMode(ledPin, OUTPUT);
Serial.begin(9600);
Wire.begin(SLAVE_ADDRESS);
pinMode(writePWMpin, OUTPUT);
Wire.onReceive(receiveData);
Wire.onRequest(sendData);
// Прерывание по нарастанию
attachInterrupt(digitalPinToInterrupt(3), D3Int, RISING);
Timer1.initialize();
Timer1.attachInterrupt(beTimeout);
}
byte test[8] = {0, 0, 0, 1, 1, 1, 1, 1}, test2[8] = {0, 0, 1, 1, 0, 0, 1, 1}, test3[16], c[32];
void toBinaryInt(int x, byte *array) {
for (int i = 15; i >= 0; i--)
{
if ((1 << i) & x) array[15 - i] = 1; else array[15 - i] = 0;
}
}
void toBinary(int x, byte *array) {
for (int i = 3; i >= 0; i--)
{
if ((1 << i) & x) array[3 - i] = 1; else array[3 - i] = 0;
}
}
void toBinaryDivPart(double divPart, byte *array) {
double _intpart;
double _divpart_tmp = divPart;
for (int i = 4; i <= 7; i++) {
divPart = _divpart_tmp * 2;
_divpart_tmp = modf(divPart, &_intpart);
array[i] = _intpart;
}
}
int pwd_count = 0;
int val = 0;
int mod_digital = 0;
void loop()
{
Serial.println(onSecondImpulsSend);
Serial.print("current mode: ");
Serial.println(mode);
//mode 5 режим работы для получения характеристик двигателя
if (mode == 5) {
val = 5;
toBinary(val, test);
toBinaryDivPart(0.475, test);
toBinary(7, test2);
toBinaryDivPart(0.475, test2);
memcpy(c, test, sizeof(byte) * 8);
memcpy(&c[8], test2, sizeof(byte) * 8);
mode = 0;
} else
//mode 7 - режим работы для управления двигателем
if (mode == 7) {
if (digitalRead(8) == 1) {
memset(c, 0, sizeof(c) / sizeof(c[0]));
mode = 0; //for stopping
}
//частота для ШИМ
if (pwd_freq>=10 && pwd_freq<60) TCCR2B = TCCR2B & B11111000 | B00000111 | 0x06;
else
if (pwd_freq>=60 && pwd_freq<100) TCCR2B=TCCR2B & 0b11111000 | 0x05; //61 Гц
else
if (pwd_freq>=100 && pwd_freq<240) TCCR2B & B11111000 | B00000110; //125
else
if (pwd_freq>=240 && pwd_freq<350) TCCR2B & B11111000 | B00000101 | 0x04; //244 Гц
else
if (pwd_freq>=350) TCCR2B & B11111000 | B00000101; //245
if (val < 15) val++; else val = 0;
pwd_count = 5 * val;
toBinary(val, test);
toBinaryDivPart(0.475, test);
toBinary(10 - val, test2);
toBinaryDivPart(0.475, test2);
toBinaryInt(onSecondImpulsSend, test3);
memcpy(c, test, sizeof(byte) * 8);
memcpy(&c[8], test2, sizeof(byte) * 8);
memcpy(&c[16], test3, sizeof(byte) * 16);
analogWrite(writePWMpin,127);
} else {
mode=0;
analogWrite(writePWMpin,0);
}
delay(1000);
}
void receiveData(int b) {
if (mode == 0) mode = Wire.read();
if (mode == 7) {
while (Wire.available()) {
pwd_freq = Wire.read()*10;
}
Serial.print("Received value: ");
Serial.println(pwd_freq);
}
}
void sendData() {
Wire.write(c, 32);
}
// Приращение счетчика по прерыванию
void D3Int() {
onSecondImpulsCounter++;
}
//каждую секунду сбрасываем счетчик
void beTimeout(){
onSecondImpulsSend=onSecondImpulsCounter;
onSecondImpulsCounter=0;
}
Я возможно невнятно выразился, или неправильно описал проблему? Попробую коротко - проблема в том что перестает работать i2c.
Подозреваю, что конфликт с библой TimerOne, беглое гугление выдало что-то похожее (не вчитывался, но вдруг поможет):
http://forum.arduino.cc/index.php?topic=198283.0
Извиняюсь что делаю такой "некропост". Проблема была в заземлении - провод еле-еле держался из-за чего и происходил сбой.
Вот так всегда бывает, пиняешь на софт, а виновен хард. Я обычно лампочкой ( светодиодом) прозваниваю, благо всегда под рукой(не забывать резистор)