Тахометр на прерываниях
- Войдите на сайт для отправки комментариев
Пт, 14/04/2017 - 09:50
Делаю тахометр. Столкнулся с проблеммой непонятных ипульсов по порту прерывания.
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. Также пробовал через резистор подтягивать на землю. Результат не меняется...
Уже хз куда копать.
Причем пару дней назад работало ... в какой то момент перестало. Пробовал менять порт на которое идет прерывание. Все тоже самое.
Если просто убрать сигнал с 19 порта меги то прерывание не срабатывает.
Так же за место UNO в качестве генератора использовал модуль на NE555. Все тоже самое.
Вешал на выход генератора светодиодик... моргает быстро. Осцилографа чтобы померить нет.
Хм переношу куски кода в пустой скетч и все работает ...
Поймал... глюки начинаются при опросе датчика ds18b20. Счем связано?
Библиотеки ONEWIRE и DallasTemperature
Наверное потому что по OneWire щедро накидано noInterrupts(); ... interrupts();
ясно ... решил что температура будет обновляться раз в 10 минут ... и забил ) 1 проскок левых данных ничего страшного