• Уважаемые посетители сайта esp8266.ru!
    Мы отказались от размещения рекламы на страницах форума для большего комфорта пользователей.
    Вы можете оказать посильную поддержку администрации форума. Данные средства пойдут на оплату услуг облачных провайдеров для сайта esp8266.ru
  • Система автоматизации с открытым исходным кодом на базе esp8266/esp32 микроконтроллеров и приложения IoT Manager. Наша группа в Telegram

ESP8266 - Время DS3231 (DS1307?) - чтение, установка

abdurino

New member
Подключение к пинам SCL и SDA я так понял произвольное и его можно менять.
По умолчанию
VCC - 3.3.V
GND - GND
SCL - 4
SDA - 5
На 2м тестовый лед, чтобы понимать что оно вообще работает )

Очень замечательно что после компиляции Arduino IDE сразу запускает программу и не надо дёргать джампер.
И при открытии com порта ESP не ресетится, так что сразу можно давать команды
show time
set time

Удачи.
Код:
#include <Wire.h>

//#define DS1307_CTRL_ID 0x68
int clockAddress = 0x68;  // This is the I2C address
byte second, minute, hour, dayOfWeek, day, dayOfMonth, month, year;


#define LCDPin 2

#define DS1307_SCL 4
#define DS1307_SDA 5



void setup() {
  // put your setup code here, to run once:
  //wire.begin(SCL, SDA)
  Wire.begin(DS1307_SCL, DS1307_SDA);
  //Wire.begin();
  Serial.begin(9600);
  pinMode(LCDPin, OUTPUT);


}

void loop() {
  digitalWrite(LCDPin, HIGH);   // turn the LED on (HIGH is the voltage level)
  delay(1000);              // wait for a second
  digitalWrite(LCDPin, LOW);    // turn the LED off by making the voltage LOW
  delay(1000);              // wait for a second


  if (Serial.available() > 0) {
    String str = Serial.readStringUntil('\n');
    if (str == "show time") {
      getDateDs1307(); // update time variables
      String s = getTimeStr();
      Serial.println(s);
    }
    if (str == "set time") {
      time_set();
    }

  }

}



// Gets the date and time from the ds1307 and prints result
void getDateDs1307() {
  // Reset the register pointer
  Wire.beginTransmission(clockAddress);
  Wire.write(byte(0x00));
  Wire.endTransmission();

  Wire.requestFrom(clockAddress, 7);

  // A few of these need masks because certain bits are control bits
  second     = bcdToDec(Wire.read() & 0x7f);
  minute     = bcdToDec(Wire.read());

  // Need to change this if 12 hour am/pm
  hour       = bcdToDec(Wire.read() & 0x3f);
  dayOfWeek  = bcdToDec(Wire.read());
  dayOfMonth = bcdToDec(Wire.read());
  day = dayOfMonth;
  month      = bcdToDec(Wire.read());
  year       = bcdToDec(Wire.read());
}
void setDateDs1307()            
{
  // Use of (byte) type casting and ascii math to achieve result.
  /*second = (byte) ((Serial.read() - 48) * 10 + (Serial.read() - 48));
  minute = (byte) ((Serial.read() - 48) *10 +  (Serial.read() - 48));
  hour  = (byte) ((Serial.read() - 48) *10 +  (Serial.read() - 48));
  dayOfWeek = (byte) (Serial.read() - 48);
  dayOfMonth = (byte) ((Serial.read() - 48) *10 +  (Serial.read() - 48));
  month = (byte) ((Serial.read() - 48) *10 +  (Serial.read() - 48));
  year= (byte) ((Serial.read() - 48) *10 +  (Serial.read() - 48));*/

  Wire.beginTransmission(clockAddress);
  Wire.write(byte(0x00));
  Wire.write(decToBcd(second));  // 0 to bit 7 starts the clock
  Wire.write(decToBcd(minute));
  Wire.write(decToBcd(hour));    // If you want 12 hour am/pm you need to set
  // bit 6 (also need to change readDateDs1307)
  Wire.write(decToBcd(dayOfWeek));
  Wire.write(decToBcd(dayOfMonth));
  Wire.write(decToBcd(month));
  Wire.write(decToBcd(year));
  Wire.endTransmission();
}

// Convert normal decimal numbers to binary coded decimal
byte decToBcd(byte val)
{
  return ( (val / 10 * 16) + (val % 10) );
}

// Convert binary coded decimal to normal decimal numbers
byte bcdToDec(byte val)
{
  return ( (val / 16 * 10) + (val % 16) );
}


String getTimeStr() {
  String str = String(day) + "." + formatDigit(month, 2) + "." + formatDigit(year, 2) + " " + formatDigit(hour, 2) + ":" + formatDigit(minute, 2) + ":" + formatDigit(second, 2);
  return str;
}
String formatDigit(int i, int len) {
  String s = String(i);
  while (s.length() < len) {
    s = "0" + s;
  }
  return (s);
}



void time_set() {
  Serial.println("Enter Year 2 last digits");
  while (Serial.available() <= 0);
  year = Serial.parseInt();
  Serial.println(year);

  Serial.println("Month");
  while (Serial.available() <= 0);
  month = Serial.parseInt();
  Serial.println(month);

  Serial.println("Day");
  while (Serial.available() <= 0);
  day = Serial.parseInt();
  dayOfMonth = day;
  Serial.println(day);

  Serial.println("Day of Week");
  while (Serial.available() <= 0);
  dayOfWeek = Serial.parseInt();
  Serial.println(dayOfWeek);

  Serial.println("Hour");
  while (Serial.available() <= 0);
  hour = Serial.parseInt();
  Serial.println(hour);

  Serial.println("Minute");
  while (Serial.available() <= 0);
  minute = Serial.parseInt();
  Serial.println(minute);

  setDateDs1307();

  Serial.println("Time recvd OK");
}
 
Последнее редактирование:

Mоnk

Member
А что в этом коде надо добавить, чтобы температуру из DS3231 получить и показать?
 

Mоnk

Member
Никому не интересно, похоже...
Отвечу сам себе.
Код:
#include <Wire.h>
#define DS3231_SCL 4
#define DS3231_SDA 5

byte second, minute, hour, dayOfWeek, dayOfMonth, month, year, temperature;

void setup() {
  Wire.begin(DS3231_SCL, DS3231_SDA);
  Serial.begin(115200);
}
void loop() {
 
  if (Serial.available() > 0) {
    String str = Serial.readStringUntil('\n');
    if (str == "get") {
      getDateDS3231(); // update time variables
      String s = getTimeStr();     
      Serial.println("-----------show time-----------");
      Serial.println(s);
    }
    if (str == "set") {
      time_set();
    }
  }
}
void getDateDS3231() {
  Wire.beginTransmission(0x68);
  Wire.write(0x00);
  Wire.endTransmission();
  Wire.requestFrom(0x68, 7);
  second     = bcdToDec(Wire.read() & 0x7f);
  minute     = bcdToDec(Wire.read());
  hour       = bcdToDec(Wire.read() & 0x3f);
  dayOfWeek  = bcdToDec(Wire.read());
  dayOfMonth = bcdToDec(Wire.read());
  month      = bcdToDec(Wire.read());
  year       = bcdToDec(Wire.read());

//--------------------------------------------
    Wire.beginTransmission(0x68);
    Wire.write(0x11);
    Wire.endTransmission();
    Wire.requestFrom(0x68, 2);
    temperature = (Wire.read() & B01111111) + ( (Wire.read() >> 6) * 0.25 );
}
void setDateDS3231()           
{
  // Use of (byte) type casting and ascii math to achieve result.
  /*second = (byte) ((Serial.read() - 48) * 10 + (Serial.read() - 48));
  minute = (byte) ((Serial.read() - 48) *10 +  (Serial.read() - 48));
  hour  = (byte) ((Serial.read() - 48) *10 +  (Serial.read() - 48));
  dayOfWeek = (byte) (Serial.read() - 48);
  dayOfMonth = (byte) ((Serial.read() - 48) *10 +  (Serial.read() - 48));
  month = (byte) ((Serial.read() - 48) *10 +  (Serial.read() - 48));
  year= (byte) ((Serial.read() - 48) *10 +  (Serial.read() - 48));*/
  Wire.beginTransmission(0x68);
  Wire.write(byte(0x00));
  Wire.write(decToBcd(second));  // 0 to bit 7 starts the clock
  Wire.write(decToBcd(minute));
  Wire.write(decToBcd(hour));    // If you want 12 hour am/pm you need to set
  // bit 6 (also need to change readDateDs1307)
  Wire.write(decToBcd(dayOfWeek));
  Wire.write(decToBcd(dayOfMonth));
  Wire.write(decToBcd(month));
  Wire.write(decToBcd(year));
  Wire.endTransmission();
}
// Convert normal decimal numbers to binary coded decimal
byte decToBcd(byte val)
{
  return ( (val / 10 * 16) + (val % 10) );
}
// Convert binary coded decimal to normal decimal numbers
byte bcdToDec(byte val)
{
  return ( (val / 16 * 10) + (val % 16) );
}
String getTimeStr() {
  String str = String(dayOfMonth) + "." + formatDigit(month, 2) + "." + formatDigit(year, 2) + " " + dayOfWeek + " " + formatDigit(hour, 2) + ":" + formatDigit(minute, 2) + ":" + formatDigit(second, 2) + " temperature " + temperature;
  return str;
}
String formatDigit(int i, int len) {
  String s = String(i);
  while (s.length() < len) {
    s = "0" + s;
  }
  return (s);
}
void time_set() {
  Serial.println("Enter Year 2 last digits");
  while (Serial.available() <= 0);
  year = Serial.parseInt();
  Serial.println(year);
  Serial.println("Month");
  while (Serial.available() <= 0);
  month = Serial.parseInt();
  Serial.println(month);
  Serial.println("dayOfMonth");
  while (Serial.available() <= 0);
  dayOfMonth = Serial.parseInt();
  Serial.println(dayOfMonth);
  Serial.println("Day of Week");
  while (Serial.available() <= 0);
  dayOfWeek = Serial.parseInt();
  Serial.println(dayOfWeek);
  Serial.println("Hour");
  while (Serial.available() <= 0);
  hour = Serial.parseInt();
  Serial.println(hour);
  Serial.println("Minute");
  while (Serial.available() <= 0);
  minute = Serial.parseInt();
  Serial.println(minute);
  Serial.println("Second");
  while (Serial.available() <= 0);
  second = Serial.parseInt();
  Serial.println(second);
 
  setDateDS3231();
  Serial.println("Time recvd OK");
}
 
Народ, так какой всетаки на ESP8266 SCL, а какой SDA? У вас 4 и 5, а вот тут наоборот. Но я и так и так пробовал. Я конечно упростил. Просто время брал.
Код:
#include <Wire.h>

int clockAddress = 0x68;  // This is the I2C address
byte second, minute, hour, dayOfWeek, day, dayOfMonth, month, year;


#define LCDPin 2

#define DS1307_SCL D1
#define DS1307_SDA D2

void setup() {
  Wire.begin(DS1307_SCL, DS1307_SDA);
  Serial.begin(9600);
  pinMode(LCDPin, OUTPUT);
}

void loop() {
  digitalWrite(LCDPin, HIGH);   // turn the LED on (HIGH is the voltage level)
  delay(1000);              // wait for a second
  digitalWrite(LCDPin, LOW);    // turn the LED off by making the voltage LOW
  delay(1000);              // wait for a second


  //if (Serial.available() > 0) {
    //String str = Serial.readStringUntil('\n');
    //if (str == "show time") {
      getDateDs1307(); // update time variables
      Serial.print(day);
      Serial.print(" ");
      Serial.print(hour);
      Serial.print(":");
      Serial.print(minute);
      Serial.print(":");
      Serial.print(second);
      Serial.print("-----");
      Serial.println(year);
      //String s = getTimeStr();
      //Serial.println(s);
    //}
    //if (str == "set time") {
     // time_set();
    //}

  //}

}
У меня время не меняется и выдает чушь!

165 45:165:85-----165
165 45:165:85-----165
165 45:165:85-----165
165 45:165:85-----165
165 45:165:85-----165
165 45:165:85-----165
 

Mоnk

Member
#define DS1307_SCL D1 #define DS1307_SDA D2
Будем надеяться, что компилятор понимает, что такое Д1 и Д2.
какой всетаки на ESP8266 SCL, а какой SDA
Какой укажите, такой и будет.
C++:
// --------------------------------------
// i2c_scanner
//
// Version 1
//    This program (or code that looks like it)
//    can be found in many places.
//    For example on the Arduino.cc forum.
//    The original author is not know.
// Version 2, Juni 2012, Using Arduino 1.0.1
//     Adapted to be as simple as possible by Arduino.cc user Krodal
// Version 3, Feb 26  2013
//    V3 by louarnold
// Version 4, March 3, 2013, Using Arduino 1.0.3
//    by Arduino.cc user Krodal.
//    Changes by louarnold removed.
//    Scanning addresses changed from 0...127 to 1...119,
//    according to the i2c scanner by Nick Gammon
//    http://www.gammon.com.au/forum/?id=10896
// Version 5, March 28, 2013
//    As version 4, but address scans now to 127.
//    A sensor seems to use address 120.
// Version 6, November 27, 2015.
//    Added waiting for the Leonardo serial communication.
//
//
// This sketch tests the standard 7-bit addresses
// Devices with higher bit address might not be seen properly.
//

#include <Wire.h>
#define SCL_pin     0   //  D3  ---------- I2C SCL
#define SDA_pin     2   //  D4  ---------- I2C SDA

void setup()
{
  Wire.begin(SDA_pin, SCL_pin);

  Serial.begin(115200);
  while (!Serial);             // Leonardo: wait for serial monitor
  Serial.println("\nI2C Scanner");
}


void loop()
{
  byte error, address;
  int nDevices;

  Serial.println("Scanning...");

  nDevices = 0;
  for(address = 1; address < 127; address++ )
  {
    // The i2c_scanner uses the return value of
    // the Write.endTransmisstion to see if
    // a device did acknowledge to the address.
    Wire.beginTransmission(address);
    error = Wire.endTransmission();

    if (error == 0)
    {
      Serial.print("I2C device found at address 0x");
      if (address<16)
        Serial.print("0");
      Serial.print(address,HEX);
      Serial.println("  !");

      nDevices++;
    }
    else if (error==4)
    {
      Serial.print("Unknow error at address 0x");
      if (address<16)
        Serial.print("0");
      Serial.println(address,HEX);
    }   
  }
  if (nDevices == 0)
    Serial.println("No I2C devices found\n");
  else
    Serial.println("done\n");

  delay(5000);           // wait 5 seconds for next scan
}
 

CodeNameHawk

Moderator
Команда форума
Скажите а ведь батарейка не нужна? должны они без батарейки работать?
Нужна. Могут без батарейки, если подать нужное питание вместо батарейки.
В первый раз часы надо запустить, установите произвольное или актуальное время и так каждый раз, если нет батарейки.
 

enjoynering

Well-known member
Если писать просто 4 и 5, то компилятор воспринимает это как GPIO4 и GPIO5. Если глянуть на распиновку той же WEMOS становится очевидно, что GPIO4, GPIO5 и D4, D5 не одно и тоже.
 

Mоnk

Member
Ну у парня все логично. D1 D2. Если мне память не изменяет, в случае вемоса надо было таблицу соответствия в эскиз включать.
 
Нужна. Могут без батарейки, если подать нужное питание вместо батарейки.
В первый раз часы надо запустить, установите произвольное или актуальное время и так каждый раз, если нет батарейки.
Я понимаю, что без батарейки часы не будут помнить время при выключении питания. Это ладно. Сеня смущают такие странные цифры и то что значение секунд не меняется. Я батарейку сейчас для тестирования не подключал. Нужна ли она чтобы часы просто ходили? Не могут ли быть такие странные цифры из-за ее отсутствия? Может у меня микросхема нерабочая? rtc.getMonthStrожет кто знает на каких выводах какие сигналы должны быть, ну кроме +5 и земли?
 

CodeNameHawk

Moderator
Команда форума
Я батарейку сейчас для тестирования не подключал. Нужна ли она чтобы часы просто ходили?
Ответ тот же,
Нужна. Могут без батарейки, если подать нужное питание вместо батарейки.
А еще нужна инициализация часов, чего нету в вашем коде.

Возьмите готовую библиотеку
https://github.com/Makuna/Rtc
, что рекомендуют тут https://arduino-esp8266.readthedocs.io/en/latest/libraries.html#ticker

Если уже какие то установили - сотрите.
 
Последнее редактирование:
Скорость на порту поменял все пошло.
Scanning...
I2C device found at address 0x68 !
done
Т.е. типа он ее видит, но время почему-то то ли не идет, толи считывается неверно.
Батарейку подключил. Вообще с батарейкой подивился. Я думал там как в биосе на матери есть - хорошо, все помнит, нет - значит каждый раз дату и время писать, если нет NTP сервера, ну и все свои настрогйки, но работать будет.
 
Скачал свежую библиотеку DS1307.h и взял пример из нее. СРазу все заработало как надо.
Код:
/*
  DS1307 RTC (Real-Time-Clock) Example

  Uno       A4 (SDA), A5 (SCL)
  Mega      20 (SDA), 21 (SCL)
  Leonardo   2 (SDA),  3 (SCL)
 */

#include <Wire.h>
#include <DS1307.h>


DS1307 rtc;


void setup()
{
  //init Serial port
  Serial.begin(9600);
  while(!Serial); //wait for serial port to connect - needed for Leonardo only

  //init RTC
  Serial.println("Init RTC...");
  rtc.begin();

  //only set the date+time one time
   rtc.set(0, 0, 8, 02, 01, 2021); //08:00:00 24.12.2014 //sec, min, hour, day, month, year

  //stop/pause RTC
  // rtc.stop();

  //start RTC
  rtc.start();
}


void loop()
{
  uint8_t sec, min, hour, day, month;
  uint16_t year;

  //get time from RTC
  rtc.get(&sec, &min, &hour, &day, &month, &year);

  //serial output
  Serial.print("\nTime: ");
  Serial.print(hour, DEC);
  Serial.print(":");
  Serial.print(min, DEC);
  Serial.print(":");
  Serial.print(sec, DEC);

  Serial.print("\nDate: ");
  Serial.print(day, DEC);
  Serial.print(".");
  Serial.print(month, DEC);
  Serial.print(".");
  Serial.print(year, DEC);

  //wait a second
  delay(1000);
}
 
Заработало на макетке. А вот на основно плате так и выдает эти неправильные даты. Но! Там у меня еще датчик bme/bmp280. Он тоже по i2c, но на D5 и D6 и работает с wire.h и показывает верные данные.
Сканер же на этой плате выдает то же
Scanning...
I2C device found at address 0x68 !
done
Вот только какое устройство он видит? Не мешают ли они друг другу?
 

Mоnk

Member
I2C device found at address 0x68 !
Ура! Мелкосхема жива.
Пробуем
C++:
#include <Wire.h>       //---------- I2C

#define SCL_pin     0   //---------- I2C
#define SDA_pin     2   //---------- I2C

void setup()
{
  Serial.begin(115200);
  Wire.begin(SDA_pin, SCL_pin); //---------- I2C
}
 
void loop()
{
  if (Serial.available() > 0)
  {
    String str = Serial.readStringUntil('\n');
    if (str == "get")
    {
      getDateDS3231(); // update time variables
      String s = getTimeStr();     
      Serial.println("-----------show time-----------");
      Serial.println(s);
    }
    if (str == "set")
    {
      time_set();
    }
  }
}
 
void getDateDS3231() {
  Wire.beginTransmission(0x68);
  Wire.write(0x00);
  Wire.endTransmission();
  Wire.requestFrom(0x68, 7);
  second     = bcdToDec(Wire.read() & 0x7f);
  minute     = bcdToDec(Wire.read());
  hour       = bcdToDec(Wire.read() & 0x3f);
  dayOfWeek  = bcdToDec(Wire.read());
  dayOfMonth = bcdToDec(Wire.read());
  month      = bcdToDec(Wire.read());
  year       = bcdToDec(Wire.read());

//--------------------------------------------
    Wire.beginTransmission(0x68);
    Wire.write(0x11);
    Wire.endTransmission();
    Wire.requestFrom(0x68, 2);
    temperature = (Wire.read() & B01111111) + ( (Wire.read() >> 6) * 0.25 );
}
 
void setDateDS3231()           
{
  // Use of (byte) type casting and ascii math to achieve result.
  /*second = (byte) ((Serial.read() - 48) * 10 + (Serial.read() - 48));
  minute = (byte) ((Serial.read() - 48) *10 +  (Serial.read() - 48));
  hour  = (byte) ((Serial.read() - 48) *10 +  (Serial.read() - 48));
  dayOfWeek = (byte) (Serial.read() - 48);
  dayOfMonth = (byte) ((Serial.read() - 48) *10 +  (Serial.read() - 48));
  month = (byte) ((Serial.read() - 48) *10 +  (Serial.read() - 48));
  year= (byte) ((Serial.read() - 48) *10 +  (Serial.read() - 48));*/
 
  Wire.beginTransmission(0x68);
  Wire.write(byte(0x00));
  Wire.write(decToBcd(second));  // 0 to bit 7 starts the clock
  Wire.write(decToBcd(minute));
  Wire.write(decToBcd(hour));    // If you want 12 hour am/pm you need to set
  // bit 6 (also need to change readDateDs1307)
  Wire.write(decToBcd(dayOfWeek));
  Wire.write(decToBcd(dayOfMonth));
  Wire.write(decToBcd(month));
  Wire.write(decToBcd(year));
  Wire.endTransmission();
}
 
// Convert normal decimal numbers to binary coded decimal
byte decToBcd(byte val)
{
  return ( (val / 10 * 16) + (val % 10) );
}
 
// Convert binary coded decimal to normal decimal numbers
byte bcdToDec(byte val)
{
  return ( (val / 16 * 10) + (val % 16) );
}
 
 
String getTimeStr() {
  String str = String(dayOfMonth) + "." + formatDigit(month, 2) + "." + formatDigit(year, 2) + " " + dayOfWeek + " " + formatDigit(hour, 2) + ":" + formatDigit(minute, 2) + ":" + formatDigit(second, 2) + " temperature " + temperature;
  return str;
}
String formatDigit(int i, int len) {
  String s = String(i);
  while (s.length() < len) {
    s = "0" + s;
  }
  return (s);
}
 
void time_set() {
  Serial.println("Enter Year 2 last digits");
  while (Serial.available() <= 0);
  year = Serial.parseInt();
  Serial.println(year);
 
  Serial.println("Month");
  while (Serial.available() <= 0);
  month = Serial.parseInt();
  Serial.println(month);
 
  Serial.println("dayOfMonth");
  while (Serial.available() <= 0);
  dayOfMonth = Serial.parseInt();
  Serial.println(dayOfMonth);
 
  Serial.println("Day of Week");
  while (Serial.available() <= 0);
  dayOfWeek = Serial.parseInt();
  Serial.println(dayOfWeek);
 
  Serial.println("Hour");
  while (Serial.available() <= 0);
  hour = Serial.parseInt();
  Serial.println(hour);
 
  Serial.println("Minute");
  while (Serial.available() <= 0);
  minute = Serial.parseInt();
  Serial.println(minute);
 
  Serial.println("Second");
  while (Serial.available() <= 0);
  second = Serial.parseInt();
  Serial.println(second);
 
  setDateDS3231();
 
  Serial.println("Time recvd OK");
}
В терминале вводим get
Показываем, что получилось.
Ну ессно пины в эскизе свои прописать - подключить. И не обязательно для БМП и 3231 делать две квадратные шины.
 
Ибо БМП и 3231 на одной шине прекрасно работают.
А это нормально, что видно только одно устройство. Я начинающий так сказать. bmp я прописывал 0х67 в самой библиотеке, 1307 0х68, а почему видна только 0х68. Хотя bmp точно работает. Температуру, влажность и давление выдает.
В вашем примере получается оба устройства через wire.h работают, но вы указываете только 2 контакта, а у меня bmp на D6 и D5, а часы на D2 и D1. И на макетке я часы тестировал с DS1307.h, с wire.h они не работали.
 
Сверху Снизу