Отключение i2c после нескольких прерываний.

Alpenland
Offline
Зарегистрирован: 13.06.2016

Здравствуйте уважаемые форумчане.

По прерыванию я считаю импульсы, потом количество импульсов по таймеру сбрасываю, импульсы насчитанные за секунду передаю по 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;
}


 

Alpenland
Offline
Зарегистрирован: 13.06.2016

Я возможно невнятно выразился, или неправильно описал проблему? Попробую коротко - проблема в том что перестает работать i2c. 

DIYMan
DIYMan аватар
Offline
Зарегистрирован: 23.11.2015

Подозреваю, что конфликт с библой TimerOne, беглое гугление выдало что-то похожее (не вчитывался, но вдруг поможет):

http://forum.arduino.cc/index.php?topic=198283.0

Alpenland
Offline
Зарегистрирован: 13.06.2016

Извиняюсь что делаю такой "некропост". Проблема была в заземлении - провод еле-еле держался из-за чего и происходил сбой.

Mr.Privet
Mr.Privet аватар
Offline
Зарегистрирован: 17.11.2015

Вот так всегда бывает, пиняешь на софт, а виновен хард. Я обычно лампочкой ( светодиодом) прозваниваю, благо всегда под рукой(не забывать резистор)