Библиотека leOS

doleynikov
Offline
Зарегистрирован: 30.01.2015

Приветствую,

Кто-нибудь использует библиотеку leOS для вызова функций через определенные промежутки?

У меня есть проектик: часы на Arduino nano - dc1307 - lm35 - и LCD 16*2.

Если просто в основном цикле все делать - работает. Если меняю код, чтобы выхов часов происходил раз в секунду - все ломается. Вернее раз 15 этот цикл отрабатывает. За это время индикатор заполняется мусором. Вероятно это из-за взаимной неприязни каких-то библиотек?

ИСХОДНИК:

#include "Arduino.h"
#include <Wire.h>
#include <DS1307.h>
#include <LiquidCrystal_I2C.h>
#include <leOS2.h>
leOS2 myOS;

#define printByte(args)  write(args);

LiquidCrystal_I2C lcd(0x27, 16, 2);

byte degree[8]  = {  B01000,  B10100,  B01000,  B00000,  B00000,  B00000,  B00000,  B00000};

byte moon[8][8] = {
  {    B10001,    B00111,    B00111,    B01111,    B01111,    B00111,    B00111,    B10001  },
  {    B10001,    B11100,    B11100,    B11110,    B11110,    B11100,    B11100,    B10001  },
  {    B10001,    B00011,    B00011,    B00011,    B00011,    B00011,    B00011,    B10001  },
  {    B10001,    B11000,    B11000,    B11000,    B11000,    B11000,    B11000,    B10001  },
  {    B10000,    B00000,    B00000,    B00000,    B00000,    B00000,    B00000,    B10000  },
  {    B00001,    B00000,    B00000,    B00000,    B00000,    B00000,    B00000,    B00001  },
  {    B10001,    B00110,    B00100,    B01100,    B01100,    B00100,    B00110,    B10001  },
  {    B10001,    B01100,    B00100,    B00110,    B00110,    B00100,    B01100,    B10001  }
};

volatile int eval1 = 0;
volatile   int TempSensor = 1;
volatile   int valTempSensor = 0;
volatile   float Term;

volatile   int Hour = 0;
volatile   int Minute = 0;
volatile   int Second = 0;
volatile   int Year = 0;
volatile   int Month = 0;
volatile   int Day = 0;

void setup() {

  lcd.init();                      // initialize the lcd
  lcd.backlight();
  lcd.clear();
  lcd.createChar(0, degree);
  analogReference(INTERNAL);


  myOS.begin(); //initialize the scheduler

  //add the tasks
  myOS.addTask(DisplayClock, myOS.convertMs(1000));

  Serial.begin(9600);
  Serial.println("(===============START==================)");

  DisplayClock();
}

void DisplayClock (void)
{
  int i;
 

  Hour = RTC.get(DS1307_HR, true); // Получаем значение текущего часа
  Minute = RTC.get(DS1307_MIN, false);
  Second = RTC.get(DS1307_SEC, false);
  Year   = RTC.get(DS1307_YR, false);
  Month  = RTC.get(DS1307_MTH, false);
  Day    = RTC.get(DS1307_DATE, false);

  valTempSensor = 0;
  for (int i = 0; i < 10; i++) { // Average 10 readings for accurate reading
    valTempSensor += analogRead(TempSensor);
  }
  Term = (1.1 * valTempSensor * 10) / 1023;

  getPhase(Year, Month,  Day);

  lcd.setCursor(0, 0); // устанавливаем позицию курсора на экране (на один символ правее левого верхнего угла)
  lcd.print(addZero(Hour));
  lcd.print(":");
  lcd.print(addZero(Minute));
  lcd.print(":");
  lcd.print(addZero(Second)); // Выводим время
  lcd.setCursor(9, 0);
  lcd.print(int(Term));
  lcd.printByte(0);
  lcd.print("C ");
  lcd.setCursor(0, 1);
  lcd.print(addZero(Day));
  lcd.print("/");
  lcd.print(addZero(Month));
  lcd.print("/");
  lcd.print(addZero(Year));
  lcd.setCursor(14, 1);
  lcd.printByte(1);
  lcd.printByte(2);
}


void loop() {

  Serial.print(addZero(Hour));
  Serial.print(":");
  Serial.print(addZero(Minute));
  Serial.print(":");
  Serial.print(addZero(Second)); // Выводим время
  Serial.print(" // ");

  Serial.print(int(Term));
  Serial.print("C // ");
  Serial.print(addZero(Day));
  Serial.print("/");
  Serial.print(addZero(Month));
  Serial.print("/");
  Serial.print(addZero(Year));
  Serial.println("(======================================)");

//  delay(2000);
  // DisplayClock();
}

char getPhase(int Y, int M, int D) {
  double AG, IP;
  char phase;
  long YY, MM, K1, K2, K3, JD;
  YY = Y - floor((12 - M) / 10);
  MM = M + 9;
  if (MM >= 12) MM = MM - 12;

  K1 = floor(365.25 * (YY + 4712));
  K2 = floor(30.6 * MM + 0.5);
  K3 = floor(floor((YY / 100) + 49) * 0.75) - 38;

  JD = K1 + K2 + D + 59;
  if (JD > 2299160)
    JD = JD - K3;

  IP = normalize((JD - 2451550.1) / 29.530588853);
  AG = IP * 29.53;
  if (AG < 1.84566)
  {
    lcd.createChar(1, moon[4]);
    lcd.createChar(2, moon[5]);
  }
  else if (AG < 5.53699)
  {
    lcd.createChar(1, moon[4]);
    lcd.createChar(2, moon[1]);
  }
  else if (AG < 9.22831)
  {
    lcd.createChar(1, moon[4]);
    lcd.createChar(2, moon[7]);
  }
  else if (AG < 12.91963)
  {
    lcd.createChar(1, moon[2]);
    lcd.createChar(2, moon[1]);
  }
  else if (AG < 16.61096)
  {
    lcd.createChar(1, moon[0]);
    lcd.createChar(2, moon[1]);
  }
  else if (AG < 20.30228)
  {
    lcd.createChar(1, moon[0]);
    lcd.createChar(2, moon[3]);
  }
  else if (AG < 23.99361)
  {
    lcd.createChar(1, moon[0]);
    lcd.createChar(2, moon[5]);
  }
  else if (AG < 27.68493)
  {
    lcd.createChar(1, moon[6]);
    lcd.createChar(2, moon[5]);
  }
  else
  {
    lcd.createChar(1, moon[4]);
    lcd.createChar(2, moon[5]);
  }

  phase = AG;
  return phase;
}

double normalize(double v) {           // normalize moon calculation between 0-1
  v = v - floor(v);
  if (v < 0) v = v + 1;
  return v;
}

String addZero(int val)
{
  if (val < 10) return "0" + String(val);
  else return String(val);
}

 

vitalikost
Offline
Зарегистрирован: 28.11.2014

Тоже работал с данной библиотекой, ну потоп перешел на 

http://www.doctormonk.com/2012/01/arduino-timer-library.html

В данный момент в моем проекте реализовано 3 таймера, пока проблем не обнаружено(ds1307,DHt11,DS18b20,TFT 2.4, Mega). 

 

doleynikov
Offline
Зарегистрирован: 30.01.2015

Спасибо. А можно примерчик? у меня есть задумка: сделать простую игру в основном цикле на дисплее от Nokia5051 , чтобы кнопочками рулить, а часики пусть "параллельно" независимо идут на соседнем экране. Получится такое?

doleynikov
Offline
Зарегистрирован: 30.01.2015

Почитал про библиотеку - она мне не подойдет. Мне нужно прерывать основную программу по таймеру, а тут основной цикл занят тем, что вызывает update(). Тут или разбираться с leOS либо снять с RTC тактитующий импульс и по нему вызывать прерывания как-то.

trembo
trembo аватар
Offline
Зарегистрирован: 08.04.2011

Не "прерывать основную программу по таймеру",   а крутится в лупе считывая миллис и реагируя не получится?
И как положено  быстро выполнять нужное прерывание не тормозящее этот луп?

Миллис- это тот-же таймер.........

vitalikost
Offline
Зарегистрирован: 28.11.2014

Еще есть MsTimer2 и SimpleTimer. Может они помогут. У меня в все просто, на TFT идет вывод информации от датчиков. А опрос датчиков идет по таймерам, там же и часть кода для перерисовки экрана, ну не всего а только части(Тупа сначала черный квадрат, а потом полезную информацию).  Также задействовал тач скин, ну для корректной работы сначала блокирую update(), делаю все что мне нужно, а потом опять запускаю update(). Как то так.

Radjah
Offline
Зарегистрирован: 06.08.2014

http://playground.arduino.cc/Main/Printf Ну же. :)

И еще у тебя есть часы с тактирующим выходом.

trembo
trembo аватар
Offline
Зарегистрирован: 08.04.2011
doleynikov
Offline
Зарегистрирован: 30.01.2015

Да знаю я про printf. не в нем загвоздка. Хотя, спасибо за напоминание - сильно уменьшит длину кода ;-)

 

А вот про тактирование хотелось бы по подробнее. Я понял, что с пина SQ в часиках можно снимать прямоугольные импульсы разной частоты, но как это сделать на практике - не понял. Я еще нуб в таком деле ;-)

Правильно ли я вижу мир?:

1) взять и соединить SQ на какой-то пин ардуино (кстати, у меня NANO, как найти правильный пин?) и вкрючить резистор 10Ком между этой точкой и +5v

2) включить генерацию импульсов на часиках

3) воспользоваться штатным механизмом attachInterrupt(), чтобы вызывать программу отображения часов по тактовому импульсу.

4) в основном цикле программы выполнять любые действия

vitalikost
Offline
Зарегистрирован: 28.11.2014

Следующие функции позволяют управлять работой генератора тактовых импульсов, выдающих определенные частоты на выход SQW/OUT:

setSQWRate(rate) – устанавливает одну из четырех возможных частот на выходе SQW/OUT. Параметр rate может принимать следующие значения:

SQW_RATE_1
SQW_RATE_4K
SQW_RATE_8K
SQW_RATE_32K



Они устанавливают частоты 1гц, 4096Гцб 8192Гц и 32768Гц соответственно. Генерация запускается отдельной командой, рассмотренной ниже:

 

enableSQW(booleanvalue) – запускает или останавливает вывод частоты, заданной командой setSQWRate(rate) и выдаваемой на выход SQW/OUT. Параметр booleanvalue может принимать значение TRUE (вывод запускается) и FALSE (вывод останавливается).

С выходом SQW/OUT работает еще одна команда:

setOutput(booleanvalue) – она позволяет установить на выходе высокий или низкий логический уровень. Параметр booleanvalue может принимать значение TRUE (устанавливается уровень лог. 1) и FALSE (устаналвивается уровень лог. 0). ВНИМАНИЕ! Эта команда не работает, если перед этим была вызвана команда enableSQW(TRUE). Т. е. выставлять логические уровни можно только тогда, когда вывод частоты отключен.

Ну вот, вроде бы и все… И на закуску – еще раз полезные ссылки:

doleynikov
Offline
Зарегистрирован: 30.01.2015

Спасибо. Это функции какой-то библиотеки?

Я нашел практический пример включения секундных импульсов:

  Wire.begin();
  Wire.beginTransmission(0x68);
  Wire.write(0x00);
  Wire.write(0x00);
  Wire.endTransmission();
  Wire.beginTransmission(0x68);
  Wire.write(0x07);
  Wire.write(0x10);  // Set Square Wave to 1 Hz
  Wire.endTransmission();

Кстати, в библиотечке, что я использую, есть функции readSqwPinMode  writeSqwPinMode (и даже пример!) . Попробую их заюзать.
 

vitalikost
Offline
Зарегистрирован: 28.11.2014

Библиотеку брал тут:

http://www.rinkydinkelectronics.com/library.php?id=34