Тахометр на прерываниях

flat
Offline
Зарегистрирован: 05.02.2015

Делаю тахометр. Столкнулся с проблеммой непонятных ипульсов по порту прерывания. 

1 Ардуинка UNO выполняет роль генератора импульсов. 

По сериалу выводил время включения выключения порта. вроде тут все правильно. но на всякий случай код.

unsigned long int time;
//unsigned long int time2;
float wait, oborots;

void setup() {

  pinMode(13, OUTPUT);
  time = millis();
  Serial.begin (9600);
  oborots = 800;
  wait = (1000000 / (oborots / 60));
}

void loop() {
  if ((micros() - time) > (wait)) {
    digitalWrite (13, HIGH);
    time = micros();
    digitalWrite (13, LOW);
  }
}

2 Ардуина мега. прерывание 4 (19 порт).  подключен tft экран 2.4, поэтому кода больше чем надо для тахо. 

#include <OneWire.h> // библиотека связи с датчиком температуры
#include <DallasTemperature.h> // библиотека датика температры
#include <TouchScreen.h> //Библиотека сенсорного экрана
#include <Adafruit_GFX.h>// подключаем библотеку экрана
#include <gfxfont.h>// фонт для вывода
#include <MCUFRIEND_kbv.h> // драйвер экрана
#include <SD.h> //Библиотека SD карты
#include <SPI.h> // Библиотека SPI для SD карты

#define LCD_RD   A0 //для LCD
#define LCD_WR   A1 //и для LCD и для сенсора    
#define LCD_RS   A2 //и для LCD и для сенсора         
#define LCD_CS   A3 //для LCD
#define BLACK           0x0000
#define BLUE            0x001A
#define RED             0xFBEF
#define GREEN           0x07E0
//#define CYAN            0x33FF
#define CYAN            0xDDFF
#define MAGENTA         0xF81F
#define YELLOW          0xFFE0
#define WHITE           0xFFFF
#define YM 7   // для сенсора
#define XP 6   // для сенсора 28FF93107216038D

int pinTemp = 48;//порт подключения датчика температур
int temppres = 1;

//SD CARD
//SD_SS=CS=10 SD_DI=MOSI=11 SD_DO=MISO=12 SD_SCK=CLK=13
#define SD_CS  53 //пин картридера
File myFile;
uint8_t G = 0x0000; // данные чтения с карты
uint8_t B = 0x0000; // данные чтения с карты
//pinMode(53, OUTPUT);

MCUFRIEND_kbv tft;
OneWire oneWire(pinTemp);//библиотека для температуры
DallasTemperature tempsens(&oneWire); ;//библиотека для температуры

DeviceAddress term1 = {0x28, 0xFF, 0x93, 0x10, 0x72, 0x16, 0x03, 0x8D}; // адрес датчика температуры 28FF93107216038D

volatile unsigned long int time = 0; //для учета оборотов
volatile unsigned long int time_last = 0;//для учета оборотов
volatile unsigned long int rpm_array[5] = {0, 0, 0, 0, 0};//для учета оборотов
volatile unsigned long int rpm;//для учета оборотов
int unsigned long time_screen;//для ограничения вывода на экран
float x1, y1, x2, y2, h; //для вывода тахометра по кругу
int clockCenterX = 319; //для вывода тахометра по кругу
int clockCenterY = 239; //для вывода тахометра по кругу
int x3, y3, x4, y4;//для вывода тахометра по кругу
TouchScreen ts = TouchScreen(XP, LCD_RS, LCD_WR, YM, 269);// TouchScreen ts = TouchScreen(XP, YP, XM, YM, 269);
short TS_MINX = 20; //для сенсора
short TS_MINY = 20;//для сенсора
short TS_MAXX = 920;//для сенсора
short TS_MAXY = 940;//для сенсора
int Y, X;//для сенсора
int temp1; // для температуры
int tipvivoda = 1; // флаг для переключения типа отображения;


void setup()
{
  pinMode(19, INPUT);
  tempsens.begin(); //инициализация датчиков температуры
  tempsens.setResolution(term1, temppres);// установка разрешающую способности датчика
  tft.reset();
  tft.cp437(true);
  uint16_t identifier = tft.readID();
  tft.begin(identifier);
  tft.setRotation(1);
  tft.fillScreen(BLACK);
  tft.setTextSize(5);
  Serial.begin(9600);
  time_screen = millis();
  if (!SD.begin(53)) {
    Serial.println("initialization failed!");
    return;
  }

  /*SD.begin(SD_CS); // включаем картриер
  X = 0;
  Y = 0;
  delay(100);
  myFile = SD.open("1.bmp", FILE_READ); //рисуем кнопку настройки
  if (!myFile) {
    Serial.println("file opening faled");
  }
  delay(100);
  knopki();*/

  if (tipvivoda == 1) {
    riski(); //рисуем черточки и цифры
  }
  attachInterrupt(4, merilka, FALLING);
}



void loop()
{
  if ((millis() - time_screen ) > 100) {
    tempsens.requestTemperatures(); //опрос датчиков температуры
    temp1 = tempsens.getTempC(term1); //получение данных
    tft.setCursor(190, 190);
    tft.setTextColor(CYAN , BLACK);
    tft.setTextSize(6);
    if (temp1 > -1) {
      tft.print ("+");
      tft.print (temp1);
    }
    else
    {
      tft.print (temp1);
    }

  }
  if ((millis() - time_screen ) > 100)
  {
    if (tipvivoda == 0) {
      printscreen();
      time_screen = millis();
    }
    else {
      drawscreen(((rpm - 600) / 100));
      time_screen = millis();
    }
  }
  sensor();
  if ((X > 0) && (Y > 0)) {
    //detachInterrupt(4);
    if (tipvivoda == 0) {
      tipvivoda = 1;
      tft.fillScreen(BLACK);
      riski();
    } else {
      tipvivoda = 0;
      tft.fillScreen(BLACK);
      tft.setTextSize(5);
    }
    // attachInterrupt(5, merilka, RISING);
  }
}

void merilka () { //измеряем обороты
  detachInterrupt(4);
  time = (micros() - time_last);
  time_last = micros();
  rpm_array[0] = rpm_array[1];
  rpm_array[1] = rpm_array[2];
  rpm_array[2] = rpm_array[3];
  rpm_array[3] = rpm_array[4];
  rpm = (60 * (1000000 / (time))) / 100;
  rpm_array[4] = rpm * 100 ;
  rpm = (rpm_array[0] + rpm_array[1] + rpm_array[2] + rpm_array[3] + rpm_array[4]) / 5;
  Serial.println(time);
  attachInterrupt(4, merilka, FALLING);
}

void printscreen() { // выводим цифрами
  // detachInterrupt(4);
  tft.setCursor(0, 0);
  tft.setTextColor(CYAN , BLACK);
  tft.print (rpm);
  tft.print ("   ");
  //Serial.println(time);
  // attachInterrupt(5, merilka, RISING);
}

void drawscreen(int h) { //выводим стрелкой

  tft.fillTriangle(x1, y1, x2 - 4, y2 + 4, x2 + 4, y2 - 4, BLACK);
  h = h * 2;
  h = h + 180;

  x1 = 210 * cos(h * 0.0175);
  y1 = 210 * sin(h * 0.0175);
  x2 = 180 * cos(h * 0.0175);
  y2 = 180 * sin(h * 0.0175);
  x3 = (x1 + clockCenterX);
  y3 = (y1 + clockCenterY);
  x4 = (x2 + clockCenterX);
  y4 = (y2 + clockCenterY);

  tft.fillTriangle(x3, y3, x4 - 4, y4 + 4, x4 + 4, y4 - 4, CYAN);
  x1 = x3;
  x2 = x4;
  y1 = y3;
  y2 = y4;
}

void riski() { //рисуем циферблат
  tft.drawCircle(319, 239, 172, CYAN);
  tft.drawCircle(319, 239, 211, CYAN);
  for (float n = 0; n < 5; n++) {
    for (float i = -1; i < 2; i) {
      h = 183 + i * 0.25 + n * 20;
      x1 = 220 * cos(h * 0.0175);
      y1 = 220 * sin(h * 0.0175);
      x2 = 210 * cos(h * 0.0175);
      y2 = 210 * sin(h * 0.0175);
      x3 = (x1 + clockCenterX);
      y3 = (y1 + clockCenterY);
      x4 = (x2 + clockCenterX);
      y4 = (y2 + clockCenterY);
      tft.drawLine(x3, y3, x4, y4 , CYAN);
      i = i + 1;
    }
  }
  tft.setCursor(85, 215);
  tft.setTextColor(CYAN );
  tft.setTextSize(3);
  tft.print (1);
  tft.setCursor(98, 137);
  tft.print (2);
  tft.setCursor(140, 72);
  tft.print (3);
  tft.setCursor(203, 25);
  tft.print (4);
  tft.setCursor(300, 0);
  tft.print (5);
  tft.setCursor(180, 160);
  tft.setTextColor(CYAN , BLACK);
  tft.setTextSize(2);
  tft.print (utf8rus("Температура"));
  tft.setCursor(192, 175);
  tft.print (utf8rus("за бортом"));
}

String utf8rus(String source)
{
  int i, k;
  String target;
  unsigned char n;
  char m[2] = { '0', '\0' };

  k = source.length(); i = 0;

  while (i < k) {
    n = source[i]; i++;

    if (n >= 0xC0) {
      switch (n) {
        case 0xD0: {
            n = source[i]; i++;
            if (n == 0x81) {
              n = 0xA8;
              break;
            }
            if (n >= 0x90 && n <= 0xBF) n = n + 0x30;
            break;
          }
        case 0xD1: {
            n = source[i]; i++;
            if (n == 0x91) {
              n = 0xB8;
              break;
            }
            if (n >= 0x80 && n <= 0x8F) n = n + 0x70;
            break;
          }
      }
    }
    m[0] = n; target = target + String(m);
  }
  return target;
}

void sensor(void) // опрос сенсора экрана
{
  TSPoint tem = ts.getPoint();
  X = 0;
  Y = 0;
  pinMode(LCD_WR, OUTPUT);// для сенсорного экрана
  pinMode(LCD_RS, OUTPUT);// для сенсорного экрана
  if (tem.z > 0)
  {
    Y = (map(tem.x, TS_MINX, TS_MAXX, tft.height(), 0));
    X = (map(tem.y, TS_MINY, TS_MAXY, tft.width(), 0));
    X = X - 14;
    Y = Y - 14;
    if (X < 0) {
      X = 0;
    }
    if (Y < 0) {
      Y = 0;
    }
    X = X * 1.172;
    Y = Y * 1.23;
    if (X > 320) {
      X = 320;
    }
    if (Y > 240) {
      Y = 240;
    }
    //tft.drawFastHLine(X,Y,2,RED);
  }
}


void knopki() { //функция чтения с карты и вывода на экран
  for (int tem1 = 0; tem1 <= 53; tem1++)
  {
    B = myFile.read();
  }
  for (int tem1 = 0; tem1 <= 11; tem1++)
  {
    B = myFile.read();
  }
  for (int Y1 = 240; Y1 > 0; Y1--)
  {
    for (int X1 = 320; X1 > 0; X1--)
    {
      B = myFile.read();
      G = myFile.read();
      tft.drawPixel(320 - X1 + X, Y1 + Y - 1, G * 256 + B);
    }
  }
  myFile.close();
}

Замер времени между ипульсами показывает

Подключение : выходной пор UNO посажен напрямую на 19 порт MEGA. Также пробовал через резистор подтягивать на землю. Результат не меняется... 

Уже хз куда копать.

flat
Offline
Зарегистрирован: 05.02.2015

Причем пару дней назад работало ... в какой то момент перестало. Пробовал менять порт на которое идет прерывание. Все тоже самое.

Если просто убрать сигнал с 19 порта меги то прерывание не срабатывает.

Так же за место UNO  в качестве генератора использовал модуль на NE555. Все тоже самое.

Вешал на выход генератора светодиодик... моргает быстро. Осцилографа чтобы померить нет.

flat
Offline
Зарегистрирован: 05.02.2015

Хм переношу куски кода в пустой скетч и все работает ... 

Поймал... глюки начинаются при опросе датчика ds18b20. Счем связано? 

Библиотеки ONEWIRE и DallasTemperature

sadman41
Offline
Зарегистрирован: 19.10.2016

Наверное потому что по OneWire щедро накидано noInterrupts(); ...  interrupts();

 
flat
Offline
Зарегистрирован: 05.02.2015

ясно ... решил что температура будет обновляться раз в 10 минут ... и забил ) 1 проскок левых данных ничего страшного