├── .gitignore ├── .gitmodules ├── README.md ├── include ├── Connector.h ├── Device.h ├── JSONParser.h ├── OCPP_Client.h ├── README ├── Requests │ ├── AbstractHandler.h │ ├── BootNotificationConf.h │ ├── BootNotificationReq.h │ ├── Call.h │ ├── CallError.h │ ├── CallResult.h │ ├── ChangeAvailabilityConf.h │ ├── ChangeAvailabilityReq.h │ ├── Message.h │ ├── PendingCalls.h │ ├── RemoteStartTransactionConf.h │ ├── RemoteStartTransactionReq.h │ ├── RemoteStopTransactionConf.h │ ├── RemoteStopTransactionReq.h │ ├── StartTransactionConf.h │ ├── StartTransactionReq.h │ ├── StatusNotificationConf.h │ ├── StatusNotificationReq.h │ ├── StopTransactionConf.h │ └── StopTransactionReq.h ├── States │ ├── Initialization.h │ ├── Inoperative.h │ ├── Operative.h │ └── State.h ├── Types │ └── Types.h └── rtc.h ├── lib ├── README ├── RTClib-master │ ├── .github │ │ ├── ISSUE_TEMPLATE.md │ │ ├── PULL_REQUEST_TEMPLATE.md │ │ └── workflows │ │ │ └── githubci.yml │ ├── .gitignore │ ├── README.md │ ├── RTClib.cpp │ ├── RTClib.h │ ├── code-of-conduct.md │ ├── examples │ │ ├── DS3231_alarm │ │ │ └── DS3231_alarm.ino │ │ ├── datecalc │ │ │ └── datecalc.ino │ │ ├── ds1307 │ │ │ └── ds1307.ino │ │ ├── ds1307SqwPin │ │ │ └── ds1307SqwPin.ino │ │ ├── ds1307nvram │ │ │ └── ds1307nvram.ino │ │ ├── ds3231 │ │ │ └── ds3231.ino │ │ ├── interrupts1Hz │ │ │ ├── .leonardo.test.only │ │ │ ├── .mega2560.test.only │ │ │ ├── .uno.test.only │ │ │ └── interrupts1Hz.ino │ │ ├── pcf8523 │ │ │ └── pcf8523.ino │ │ ├── pcf8523Countdown │ │ │ └── pcf8523Countdown.ino │ │ ├── pcf8563 │ │ │ └── pcf8563.ino │ │ ├── pcf8563_interrupt │ │ │ └── pcf8563_interrupt.ino │ │ ├── softrtc │ │ │ └── softrtc.ino │ │ ├── timestamp │ │ │ └── timestamp.ino │ │ └── toString │ ├── keywords.txt │ ├── library.properties │ └── license.txt └── TinyWireM-master │ ├── .github │ ├── ISSUE_TEMPLATE.md │ ├── PULL_REQUEST_TEMPLATE.md │ └── workflows │ │ └── githubci.yml │ ├── README.md │ ├── TinyWireM.cpp │ ├── TinyWireM.h │ ├── USI_TWI_Master.cpp │ ├── USI_TWI_Master.h │ ├── examples │ ├── Tiny85_Temp │ │ └── Tiny85_Temp.pde │ ├── Tiny85_Temp_LCD │ │ └── Tiny85_Temp_LCD.pde │ └── Tiny85_Temp_LCD_RTC │ │ └── Tiny85_Temp_LCD_RTC.pde │ ├── keywords.txt │ └── library.properties ├── platformio.ini └── src ├── Device.cpp ├── JSONParser.cpp ├── OCPP_Client.cpp ├── Requests ├── BootNotificationConf.cpp ├── Call.cpp ├── CallError.cpp ├── CallResult.cpp ├── ChangeAvailabilityConf.cpp ├── ChangeAvailabilityReq.cpp ├── Message.cpp ├── PendingCalls.cpp ├── RemoteStartTransactionConf.cpp ├── RemoteStartTransactionReq.cpp ├── RemoteStopTransactionConf.cpp ├── RemoteStopTransactionReq.cpp ├── StartTransactionConf.cpp ├── StartTransactionReq.cpp ├── StatusNotificationConf.cpp ├── StatusNotificationReq.cpp ├── StopTransactionConf.cpp ├── StopTransactionReq.cpp └── bootNoticicationReq.cpp ├── States ├── Initialization.cpp ├── Inoperative.cpp ├── Operative.cpp └── State.cpp ├── main.cpp └── rtc.cpp /.gitignore: -------------------------------------------------------------------------------- 1 | .pio 2 | .vscode/.browse.c_cpp.db* 3 | .vscode/c_cpp_properties.json 4 | .vscode/launch.json 5 | .vscode/ipch 6 | .pio 7 | CMakeListsPrivate.txt 8 | cmake-build-*/ 9 | CMakeLists.txt 10 | .idea 11 | .DS_Store 12 | test 13 | desktop.ini 14 | .vscode -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "lib/mjson"] 2 | path = lib/mjson 3 | url = https://github.com/art-mx/mjson 4 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # OCPP Embedded Client 2 | ### Brief Description 3 | This is an STM32 Arduino implementation of an OCPP-1.6 client. Websocket communication is delegated to a VCON device (https://vcon.io/), which is providing a transparent serial-websocket bridge. JSON RPC handling is done using the mjson library from Cesanta (https://github.com/cesanta/mjson). 4 | 5 | This program's architecture is using two well known patterns - "Chain of Responsibility", used for handling requests and "State/Context" for dealing with device states. 6 | 7 | This code has been tested on an STM32F091RC with 32K RAM of which 15K are statically allocated. Flash memory occupied is ~64K. 8 | 9 | Some C++ STL components are used such as map and vector. 10 | 11 | ### Known Issues 12 | 13 | --- 14 | -------------------------------------------------------------------------------- /include/Connector.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include "Types/Types.h" 4 | 5 | class Connector { 6 | private: 7 | PinName pin_; 8 | 9 | public: 10 | Connector(PinName pin, int id): pin_(pin), id(id) {}; 11 | const int id; 12 | void SetStatus(ChargePointStatus status, ChargePointErrorCode error) { 13 | status_ = status; 14 | error_ = error; 15 | } 16 | int currentTransactionId; 17 | ChargePointStatus status_; 18 | ChargePointErrorCode error_; 19 | 20 | 21 | 22 | 23 | 24 | }; -------------------------------------------------------------------------------- /include/Device.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include "Connector.h" 5 | #include 6 | #include "Types/Types.h" 7 | 8 | using std::vector; 9 | class OCPP_Client; 10 | class State; 11 | 12 | class Device { 13 | public: 14 | Device(); 15 | ~Device(); 16 | void SetClient(OCPP_Client * client); 17 | void AddConnector(Connector * connector); 18 | Connector * GetConnector(int id); 19 | uint8_t NumConnectors(); 20 | void ReportConnectors(); 21 | void ReportConnectorStateChange(int id); 22 | void ChangeState(State * state); 23 | int GetMeterValueForTransaction(int transactionId){return 1000;} //TODO 24 | void Update(); 25 | OCPP_Client * client_{nullptr}; 26 | State * state_{nullptr}; 27 | private: 28 | std::vector connector_list_; 29 | private: 30 | 31 | }; 32 | 33 | 34 | -------------------------------------------------------------------------------- /include/JSONParser.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include "mjson.h" 4 | using std::string; 5 | 6 | bool GetDouble(const string & msg, const string & key, double * value); 7 | 8 | bool GetInteger(string & msg, const string & key, int * value); 9 | 10 | bool GetObject(string & msg, const char * key, string & value); 11 | 12 | bool GetString(const string & msg, const char * key, string & value); 13 | 14 | int check_if_frame_is_complete(char * buf, int len, string & frame); 15 | 16 | bool FindKey(const string & msg, const char * key); -------------------------------------------------------------------------------- /include/OCPP_Client.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include "mjson.h" 4 | #include "Requests/PendingCalls.h" 5 | #include "Requests/BootNotificationReq.h" 6 | #include "Requests/StatusNotificationReq.h" 7 | #include "Requests/StartTransactionReq.h" 8 | #include "Requests/StopTransactionReq.h" 9 | #include "Requests/Message.h" 10 | #include "Requests/CallResult.h" 11 | #include "Requests/Call.h" 12 | #include "Requests/CallError.h" 13 | #include "JSONParser.h" 14 | 15 | 16 | using std::string; 17 | 18 | int Sender(const char *frame, int frame_len, void *privdata); 19 | 20 | class Device; 21 | class Message; 22 | 23 | class OCPP_Client { 24 | public: 25 | struct jsonrpc_ctx ctx; 26 | Device * device_; 27 | OCPP_Client(Device * device); 28 | ~OCPP_Client(); 29 | void SetDevice(Device * device); 30 | uint32_t counter = 0; 31 | void SendBootNotification(); 32 | void SendStatusNotification(int connector, string error, string status); 33 | void SendStartTransaction(int connector, string idTag, int meterStart, string timestamp); 34 | void SendStopTransaction(int meterStop, string timestamp, int transactionId, StopTransactionReason reason); 35 | void SendCall(PendingCall * call); 36 | void ReSendCall(PendingCall* call); 37 | void SendCallResult(Msg & msg); // TODO HERE 38 | void Update(); 39 | PendingCalls * pending_calls_; 40 | BootNotificationReq * boot_notification_req; 41 | StatusNotificationReq * status_notification_req; 42 | StartTransactionReq * start_transaction_req; 43 | StopTransactionReq * stop_transaction_req; 44 | Message * message; 45 | 46 | int GetCurrentTransactionId() {return currentTransactionId_;} 47 | void SetCurrentTransactionId(int id) {currentTransactionId_ = id;} 48 | private: 49 | int currentTransactionId_; 50 | 51 | }; -------------------------------------------------------------------------------- /include/README: -------------------------------------------------------------------------------- 1 | 2 | This directory is intended for project header files. 3 | 4 | A header file is a file containing C declarations and macro definitions 5 | to be shared between several project source files. You request the use of a 6 | header file in your project source file (C, C++, etc) located in `src` folder 7 | by including it, with the C preprocessing directive `#include'. 8 | 9 | ```src/main.c 10 | 11 | #include "header.h" 12 | 13 | int main (void) 14 | { 15 | ... 16 | } 17 | ``` 18 | 19 | Including a header file produces the same results as copying the header file 20 | into each source file that needs it. Such copying would be time-consuming 21 | and error-prone. With a header file, the related declarations appear 22 | in only one place. If they need to be changed, they can be changed in one 23 | place, and programs that include the header file will automatically use the 24 | new version when next recompiled. The header file eliminates the labor of 25 | finding and changing all the copies as well as the risk that a failure to 26 | find one copy will result in inconsistencies within a program. 27 | 28 | In C, the usual convention is to give header files names that end with `.h'. 29 | It is most portable to use only letters, digits, dashes, and underscores in 30 | header file names, and at most one dot. 31 | 32 | Read more about using header files in official GCC documentation: 33 | 34 | * Include Syntax 35 | * Include Operation 36 | * Once-Only Headers 37 | * Computed Includes 38 | 39 | https://gcc.gnu.org/onlinedocs/cpp/Header-Files.html 40 | -------------------------------------------------------------------------------- /include/Requests/AbstractHandler.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | using std::string; 4 | #include "Device.h" 5 | extern HardwareSerial logser; 6 | #include "Types/Types.h" 7 | 8 | struct Msg { 9 | string raw; 10 | int type; 11 | string uid; 12 | string action; 13 | string payload; 14 | string response_payload; 15 | }; 16 | 17 | 18 | class Handler { 19 | public: 20 | // Device * device_; 21 | virtual Handler *SetNext(Handler *handler) = 0; 22 | virtual Msg Handle(Msg & msg) = 0; 23 | virtual void SetDevice(Device * device) = 0; 24 | virtual ~Handler() = default; 25 | }; 26 | 27 | 28 | class AbstractHandler : public Handler { 29 | private: 30 | Handler *next_handler_; 31 | public: 32 | Device * device_; 33 | void SetDevice(Device * device) override { 34 | device_= device; 35 | } 36 | AbstractHandler() : next_handler_(nullptr) {} 37 | 38 | // https://wiki.sei.cmu.edu/confluence/display/cplusplus/OOP52-CPP.+Do+not+delete+a+polymorphic+object+without+a+virtual+destructor 39 | virtual ~AbstractHandler() = default; 40 | 41 | Handler *SetNext(Handler *handler) override { 42 | this->next_handler_ = handler; 43 | this->next_handler_->SetDevice(device_); 44 | return handler; 45 | } 46 | 47 | Msg Handle(Msg & msg) override { 48 | if (this->next_handler_) { 49 | Handler* next = this->next_handler_; 50 | // TODO 51 | // delete this; 52 | return next->Handle(msg); 53 | } 54 | return msg; 55 | } 56 | }; -------------------------------------------------------------------------------- /include/Requests/BootNotificationConf.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "Device.h" 3 | #include "Requests/AbstractHandler.h" 4 | #include "Types/Types.h" 5 | #include "JSONParser.h" 6 | #include "States/State.h" 7 | 8 | class BootNotificationConf : public AbstractHandler { 9 | public: 10 | Msg Handle(Msg & msg) override; 11 | }; 12 | 13 | -------------------------------------------------------------------------------- /include/Requests/BootNotificationReq.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | 4 | extern "C" { 5 | #include "mjson.h" 6 | } 7 | using std::string; 8 | 9 | 10 | class BootNotificationReq { 11 | private: 12 | string chargePointModel_; 13 | string chargePointVendor_; 14 | string chargePointSerialNumber_; 15 | string firmwareVersion_; 16 | string iccid_; 17 | string imsi_; 18 | string meterSerialNumber_; 19 | string meterType_; 20 | 21 | public: 22 | BootNotificationReq() {}; 23 | // ~BootNotificationReq(); 24 | string Payload(); 25 | const string Action = "BootNotification"; 26 | 27 | /* 28 | * {"chargePointModel": "modelX", "chargePointVendor": "vendorX"} 29 | */ 30 | const char * payload_format = "{%Q: %Q, %Q: %Q}"; 31 | 32 | }; -------------------------------------------------------------------------------- /include/Requests/Call.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | //#include 6 | #include 7 | #include "Types/Types.h" 8 | #include "Requests/AbstractHandler.h" 9 | #include "JSONParser.h" 10 | #include "Device.h" 11 | 12 | class ChangeAvailabilityReq; 13 | class RemoteStartTransactionReq; 14 | class RemoteStopTransactionReq; 15 | 16 | using namespace std; 17 | #define MAX_CALL_NUM 10 // number of calls to store 18 | 19 | extern HardwareSerial logser; 20 | 21 | class Call : public AbstractHandler { 22 | public: 23 | Call(); 24 | 25 | Msg Handle(Msg & msg) override; 26 | /* 27 | * [, "", "", {}] 28 | */ 29 | const char * format = "[%d, %Q, %Q, %s]\n"; 30 | const char * MessageTypeId_key = "$[0]"; 31 | const char * UniqueId_key = "$[1]"; 32 | const char * Action_key = "$[2]"; 33 | const char * Payload_key = "$[3]"; 34 | 35 | 36 | string GenerateUniqueId() { 37 | static int i = 0; 38 | ++i; 39 | return to_string(i); 40 | } 41 | private: 42 | ChangeAvailabilityReq * ChangeAvailabilityReq_; 43 | RemoteStartTransactionReq * RemoteStartTransactionReq_; 44 | RemoteStopTransactionReq * RemoteStopTransactionReq_; 45 | }; 46 | 47 | 48 | -------------------------------------------------------------------------------- /include/Requests/CallError.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include "Requests/AbstractHandler.h" 4 | #include "Types/Types.h" 5 | #include "JSONParser.h" 6 | 7 | extern HardwareSerial logser; 8 | 9 | class CallError : public AbstractHandler { 10 | public: 11 | 12 | /* 13 | * [, "", "", "", {}] 14 | */ 15 | const char * format = "[%d, %Q, %Q, %Q, %s]\n"; 16 | const char * errorCode_key = "$[2]"; 17 | const char * errorDescription_key = "$[3]"; 18 | const char * errorDetails_key = "$[4]"; 19 | // void MessageHandler(const string & payload, Device * device); 20 | Msg Handle(Msg & msg) override; 21 | }; -------------------------------------------------------------------------------- /include/Requests/CallResult.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | 4 | #include "Requests/AbstractHandler.h" 5 | #include "Types/Types.h" 6 | #include "JSONParser.h" 7 | #include "PendingCalls.h" 8 | #include "Device.h" 9 | #include "OCPP_Client.h" 10 | 11 | 12 | class BootNotificationConf; 13 | class StatusNotificationConf; 14 | class StartTransactionConf; 15 | class StopTransactionConf; 16 | 17 | extern HardwareSerial logser; 18 | 19 | class CallResult : public AbstractHandler { 20 | public: 21 | CallResult(); 22 | /* 23 | * [, "", {}] 24 | */ 25 | const char * format = "[%d, %Q, %s]\n"; 26 | const char * MessageTypeId_key = "$[0]"; 27 | const char * UniqueId_key = "$[1]"; 28 | const char * Payload_key = "$[2]"; 29 | Msg Handle(Msg & msg) override; 30 | 31 | private: 32 | BootNotificationConf * BootNotificationConf_; 33 | StatusNotificationConf * StatusNotificationConf_; 34 | StartTransactionConf * StartTransactionConf_; 35 | StopTransactionConf * StopTransactionConf_; 36 | }; 37 | 38 | -------------------------------------------------------------------------------- /include/Requests/ChangeAvailabilityConf.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include "Types/Types.h" 4 | extern "C" { 5 | #include "mjson.h" 6 | } 7 | #include "Requests/AbstractHandler.h" 8 | #include "OCPP_Client.h" 9 | 10 | class ChangeAvailabilityConf : public AbstractHandler { 11 | public: 12 | ChangeAvailabilityConf(AvailabilityStatus status) { 13 | status_ = status; 14 | } 15 | /* 16 | * {"status": "Accepted"} 17 | */ 18 | AvailabilityStatus status_; 19 | const char * payload_format = "{%Q: %Q}"; 20 | void SetPayload(string & payload); 21 | Msg Handle(Msg & msg) override; 22 | }; -------------------------------------------------------------------------------- /include/Requests/ChangeAvailabilityReq.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include "Requests/AbstractHandler.h" 4 | #include "Types/Types.h" 5 | #include "JSONParser.h" 6 | #include "Device.h" 7 | #include "States/State.h" 8 | #include "OCPP_Client.h" 9 | 10 | class ChangeAvailabilityReq: public AbstractHandler { 11 | public: 12 | Msg Handle(Msg & msg) override; 13 | }; 14 | -------------------------------------------------------------------------------- /include/Requests/Message.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "Arduino.h" 3 | extern "C" { 4 | #include "mjson.h" 5 | } 6 | #include 7 | #include "Types/Types.h" 8 | #include "Requests/AbstractHandler.h" 9 | #include "JSONParser.h" 10 | 11 | using std::string; 12 | extern HardwareSerial logser; 13 | 14 | class Call; 15 | class CallResult; 16 | class CallError; 17 | 18 | class Message : public AbstractHandler { 19 | public: 20 | Message(); 21 | const char * MessageTypeId_key = "$[0]"; 22 | const char * UniqueId_key = "$[1]"; 23 | Msg Handle(Msg & msg) override; 24 | private: 25 | Call * call_; 26 | CallResult * callResult_; 27 | CallError * callerror_; 28 | }; -------------------------------------------------------------------------------- /include/Requests/PendingCalls.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include "Types/Types.h" 8 | 9 | using namespace std; 10 | 11 | #define MAX_CALL_NUM 10 // number of calls to store 12 | 13 | class PendingCall { 14 | public: 15 | PendingCall(string Action, string Payload); 16 | PendingCall(); 17 | ~PendingCall() = default; 18 | const uint8_t MessageTypeId = MessageType::CALL; 19 | string Action; 20 | string UniqueId; 21 | string Payload; 22 | uint32_t timestamp_; 23 | int retries = 0; 24 | /* 25 | * [, "", "", {}] 26 | */ 27 | const char * format = "[%d, %Q, %Q, %s]\n"; 28 | const char * Payload_key = "$[3]"; 29 | const char * Action_key = "$[2]"; 30 | 31 | string GenerateUniqueId() { 32 | static int i = 0; 33 | ++i; 34 | return to_string(i); 35 | } 36 | }; 37 | 38 | class OCPP_Client; 39 | 40 | class PendingCalls { 41 | private: 42 | vector call_list_; 43 | // map call_map_; 44 | public: 45 | PendingCalls(OCPP_Client * client): client_(client) {} 46 | ~PendingCalls() = default; 47 | void StoreCall(PendingCall* call); 48 | bool GetCallActionWithId(string & id, string & action); 49 | void Update(); 50 | OCPP_Client * client_; 51 | }; 52 | 53 | -------------------------------------------------------------------------------- /include/Requests/RemoteStartTransactionConf.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include "Types/Types.h" 4 | extern "C" { 5 | #include "mjson.h" 6 | } 7 | #include "Requests/AbstractHandler.h" 8 | #include "OCPP_Client.h" 9 | 10 | class RemoteStartTransactionConf : public AbstractHandler { 11 | public: 12 | RemoteStartTransactionConf() {} 13 | /* response example 14 | * {"status": "Accepted"} 15 | */ 16 | RemoteStartStopStatus status_; 17 | const char * payload_format = "{%Q: %Q}"; 18 | void SetPayload(string & payload); 19 | void SetStatus(RemoteStartStopStatus status); 20 | Msg Handle(Msg & msg) override; 21 | }; -------------------------------------------------------------------------------- /include/Requests/RemoteStartTransactionReq.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include "Requests/AbstractHandler.h" 4 | #include "Types/Types.h" 5 | #include "JSONParser.h" 6 | #include "Device.h" 7 | #include "States/State.h" 8 | #include "OCPP_Client.h" 9 | 10 | class RemoteStartTransactionConf; 11 | 12 | class RemoteStartTransactionReq: public AbstractHandler { 13 | public: 14 | RemoteStartTransactionReq(); 15 | Msg Handle(Msg & msg) override; 16 | private: 17 | RemoteStartTransactionConf * RemoteStartTransactionConf_; 18 | }; 19 | -------------------------------------------------------------------------------- /include/Requests/RemoteStopTransactionConf.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include "Types/Types.h" 4 | extern "C" { 5 | #include "mjson.h" 6 | } 7 | #include "Requests/AbstractHandler.h" 8 | #include "OCPP_Client.h" 9 | 10 | class RemoteStopTransactionConf : public AbstractHandler { 11 | public: 12 | RemoteStopTransactionConf() {} 13 | /* response example 14 | * {"status": "Accepted"} 15 | */ 16 | RemoteStartStopStatus status_; 17 | const char * payload_format = "{%Q: %Q}"; 18 | void SetPayload(string & payload); 19 | void SetStatus(RemoteStartStopStatus status); 20 | Msg Handle(Msg & msg) override; 21 | }; -------------------------------------------------------------------------------- /include/Requests/RemoteStopTransactionReq.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include "Requests/AbstractHandler.h" 4 | #include "Types/Types.h" 5 | #include "JSONParser.h" 6 | #include "Device.h" 7 | #include "States/State.h" 8 | #include "OCPP_Client.h" 9 | 10 | class RemoteStopTransactionConf; 11 | class StopTransactionReq; 12 | 13 | class RemoteStopTransactionReq: public AbstractHandler { 14 | public: 15 | RemoteStopTransactionReq(); 16 | Msg Handle(Msg & msg) override; 17 | private: 18 | RemoteStopTransactionConf * RemoteStopTransactionConf_; 19 | StopTransactionReq * StopTransactionReq_; 20 | }; 21 | -------------------------------------------------------------------------------- /include/Requests/StartTransactionConf.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "Device.h" 3 | #include "Requests/AbstractHandler.h" 4 | #include "Types/Types.h" 5 | #include "JSONParser.h" 6 | #include "States/State.h" 7 | #include "OCPP_Client.h" 8 | 9 | class StartTransactionConf : public AbstractHandler { 10 | public: 11 | Msg Handle(Msg & msg) override; 12 | }; 13 | 14 | -------------------------------------------------------------------------------- /include/Requests/StartTransactionReq.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | 4 | 5 | extern "C" { 6 | #include "mjson.h" 7 | } 8 | #include 9 | using std::string; 10 | 11 | class StartTransactionReq { 12 | 13 | public: 14 | string Payload(int connector, string idTag, int meterStart, string timestamp); 15 | const string Action = "StartTransaction"; 16 | 17 | /* 18 | * {"connectorId": 1, "idTag": "test_tag", "meterStart": 1234, "timestamp": "2021-02-25T13:01:23.684Z"} 19 | */ 20 | const char * payload_format = "{%Q: %d, %Q: %Q, %Q: %d, %Q: %Q}"; 21 | /* 22 | * {"connectorId": 1, "idTag": "test_tag", "meterStart": 1234, "reservationId": 1234, "timestamp": "2021-02-25T13:01:23.684Z"} 23 | */ 24 | const char * payload_format_reservation = "{%Q: %d, %Q: %Q, %Q: %d, %Q: %d, %Q: %Q}"; 25 | // string & Handle(string & msg); 26 | }; -------------------------------------------------------------------------------- /include/Requests/StatusNotificationConf.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "Device.h" 3 | #include "Requests/AbstractHandler.h" 4 | #include "Types/Types.h" 5 | #include "JSONParser.h" 6 | #include "States/State.h" 7 | 8 | class StatusNotificationConf : public AbstractHandler { 9 | public: 10 | Msg Handle(Msg & msg) override; 11 | }; 12 | 13 | -------------------------------------------------------------------------------- /include/Requests/StatusNotificationReq.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | using std::string; 4 | #include "Types/Types.h" 5 | #include "mjson.h" 6 | 7 | class StatusNotificationReq { 8 | public: 9 | StatusNotificationReq() {}; 10 | string Payload(int connector, string error, string status); 11 | /* required fields: 12 | * {"connectorId": = 0>, "errorCode": "", "status": ""} 13 | */ 14 | const char * payload_format = "{%Q: %d, %Q: %Q, %Q: %Q}\n"; 15 | const string Action = "StatusNotification"; 16 | 17 | }; -------------------------------------------------------------------------------- /include/Requests/StopTransactionConf.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "Device.h" 3 | #include "Requests/AbstractHandler.h" 4 | #include "Types/Types.h" 5 | #include "JSONParser.h" 6 | #include "States/State.h" 7 | #include "OCPP_Client.h" 8 | 9 | class StopTransactionConf : public AbstractHandler { 10 | public: 11 | Msg Handle(Msg & msg) override; 12 | }; 13 | 14 | -------------------------------------------------------------------------------- /include/Requests/StopTransactionReq.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include "Types/Types.h" 4 | #include "Requests/AbstractHandler.h" 5 | 6 | extern "C" { 7 | #include "mjson.h" 8 | } 9 | #include 10 | using std::string; 11 | 12 | class StopTransactionReq{ 13 | 14 | public: 15 | string Payload(int meterStop, string timestamp, int transactionId, StopTransactionReason reason); 16 | const string Action = "StopTransaction"; 17 | /* 18 | * {"meterStop": 1234, "timestamp": "2021-02-25T13:01:23.684Z", "transactionId": 1234, "reason": "Local"} 19 | */ 20 | const char * payload_format = "{%Q:%d, %Q:%Q, %Q:%d, %Q:%Q}"; 21 | 22 | }; -------------------------------------------------------------------------------- /include/States/Initialization.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "States/State.h" 3 | // #include "Types/Types.h" 4 | 5 | class Initialization : public State { 6 | public: 7 | void StateHandle_RegistrationStatus(RegistrationStatus status); 8 | 9 | // when in initialization state we're not handling anything besides Registration 10 | AvailabilityStatus StateHandle_AvailabilityStatus(AvailabilityType type) {return AVAIL_STATUS_UNDEFINED;}; 11 | void HandleTimerChange(); 12 | const std::string GetStateName(); 13 | }; -------------------------------------------------------------------------------- /include/States/Inoperative.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "States/State.h" 3 | // #include "Types/Types.h" 4 | // #include "States/Initialization.h" 5 | 6 | 7 | class Inoperative : public State { 8 | public: 9 | 10 | void StateHandle_RegistrationStatus(RegistrationStatus status) {}; 11 | AvailabilityStatus StateHandle_AvailabilityStatus(AvailabilityType type); 12 | void HandleTimerChange(); 13 | const std::string GetStateName(); 14 | }; -------------------------------------------------------------------------------- /include/States/Operative.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "States/State.h" 3 | // #include "Types/Types.h" 4 | 5 | 6 | class State; 7 | 8 | class Operative : public State { 9 | public: 10 | void StateHandle_RegistrationStatus(RegistrationStatus status) {}; 11 | AvailabilityStatus StateHandle_AvailabilityStatus(AvailabilityType type); 12 | 13 | void HandleTimerChange(); 14 | const std::string GetStateName(); 15 | }; -------------------------------------------------------------------------------- /include/States/State.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include "Device.h" 4 | #include "Types/Types.h" 5 | extern HardwareSerial logser; 6 | 7 | class Device; 8 | 9 | class State { 10 | protected: 11 | Device* device_; 12 | uint32_t last_state_change_millis_ {0}; 13 | uint32_t kAutoStateChangeThreshold{5000}; 14 | public: 15 | virtual ~State() {} 16 | void SetContext(Device* context) ; 17 | virtual const std::string GetStateName(); 18 | uint32_t GetTimerValue(); 19 | void UpdateTimerValue(); 20 | 21 | virtual void StateHandle_RegistrationStatus(RegistrationStatus status); 22 | virtual AvailabilityStatus StateHandle_AvailabilityStatus(AvailabilityType type); 23 | // virtual void HandleRegistrationStatusRejected(); 24 | // virtual void HandleAvailabilityChange(); 25 | 26 | }; -------------------------------------------------------------------------------- /include/Types/Types.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include 4 | #include 5 | using namespace std; 6 | 7 | 8 | // typedef char CiString50Type[50]; 9 | // typedef char CiString25Type[25]; 10 | typedef char CiString20Type[20]; 11 | 12 | class CiString { 13 | private: 14 | const uint8_t length_; 15 | string value_; 16 | public: 17 | CiString(uint8_t length, string value); 18 | ~CiString(); 19 | string Get(); 20 | bool Set(string value); 21 | }; 22 | 23 | class CiString20 : public CiString { 24 | public: 25 | CiString20(string value) : CiString(20, value) {}; 26 | // CiString20(): CiString(20, "") {}; 27 | }; 28 | 29 | typedef char dateTime[20]; 30 | 31 | enum RegistrationStatus { 32 | UNDEFINED = 0, 33 | ACCEPTED = 1, 34 | PENDING = 2, 35 | REJECTED = 3 36 | }; 37 | 38 | 39 | static std::map RegistrationStatusMap = { 40 | {"Accepted", ACCEPTED}, 41 | {"Rending", PENDING}, 42 | {"Rejected", REJECTED} 43 | }; 44 | 45 | enum MessageType { 46 | CALL = 2, 47 | CALLRESULT = 3, 48 | CALLERROR = 4 49 | }; 50 | 51 | // TODO split into call actions and call result actions? 52 | enum MessageAction { 53 | UNDEFINED_ACTION = 0, 54 | BOOT_NOTIFICATION, 55 | CHANGE_AVAILABILITY, 56 | STATUS_NOTIFICATION, 57 | REMOTE_START_TRANSACTION, 58 | START_TRANSACTION, 59 | REMOTE_STOP_TRANSACTION, 60 | STOP_TRANSACTION 61 | }; 62 | 63 | static std::map MessageActionNamesMap = { 64 | {"BootNotification", BOOT_NOTIFICATION}, 65 | {"ChangeAvailability", CHANGE_AVAILABILITY}, 66 | {"StatusNotification", STATUS_NOTIFICATION}, 67 | {"RemoteStartTransaction", REMOTE_START_TRANSACTION}, 68 | {"StartTransaction", START_TRANSACTION}, 69 | {"RemoteStopTransaction", REMOTE_STOP_TRANSACTION}, 70 | {"StopTransaction", STOP_TRANSACTION} 71 | }; 72 | 73 | enum AvailabilityType { 74 | INOPERATIVE = 1, 75 | OPERATIVE = 2 76 | }; 77 | 78 | static std::map AvailabilityTypeNamesMap = { 79 | {"Inoperative", INOPERATIVE}, 80 | {"Operative", OPERATIVE} 81 | }; 82 | 83 | enum AvailabilityStatus { 84 | AVAIL_STATUS_UNDEFINED = 0, 85 | AVAIL_STATUS_ACCEPTED = 1, 86 | AVAIL_STATUS_REJECTED = 2, 87 | AVAIL_STATUS_SCHEDULED = 3 88 | }; 89 | static const string AvailabilityStatusNames[4] = { 90 | "Undefined", 91 | "Accepted", 92 | "Scheduled", 93 | "Rejected" 94 | }; 95 | 96 | enum ChargePointStatus { 97 | CP_STATUS_Available, 98 | CP_STATUS_Preparing, 99 | CP_STATUS_Charging, 100 | CP_STATUS_SuspendedEVSE, 101 | CP_STATUS_SuspendedEV, 102 | CP_STATUS_Finishing, 103 | CP_STATUS_Reserved, 104 | CP_STATUS_Unavailable, 105 | CP_STATUS_Faulted 106 | }; 107 | 108 | static const string ChargePointStatusNames[9] = { 109 | "Available", 110 | "Preparing", 111 | "Charging", 112 | "SuspendedEVSE", 113 | "SuspendedEV", 114 | "Finishing", 115 | "Reserved", 116 | "Unavailable", 117 | "Faulted" 118 | }; 119 | 120 | enum ChargePointErrorCode { 121 | CP_ERROR_ConnectorLockFailure, 122 | CP_ERROR_EVCommunicationError, 123 | CP_ERROR_GroundFailure, 124 | CP_ERROR_HighTemperature, 125 | CP_ERROR_InternalError, 126 | CP_ERROR_LocalListConflict, 127 | CP_ERROR_NoError, 128 | CP_ERROR_OtherError, 129 | CP_ERROR_OverCurrentFailure, 130 | CP_ERROR_OverVoltage, 131 | CP_ERROR_PowerMeterFailure, 132 | CP_ERROR_PowerSwitchFailure, 133 | CP_ERROR_ReaderFailure, 134 | CP_ERROR_ResetFailure, 135 | CP_ERROR_UnderVoltage, 136 | CP_ERROR_WeakSignal 137 | }; 138 | static const string ChargePointErrorCodeNames[16] = { 139 | "ConnectorLockFailure", 140 | "EVCommunicationError", 141 | "GroundFailure", 142 | "HighTemperature", 143 | "InternalError", 144 | "LocalListConflict", 145 | "NoError", 146 | "OtherError", 147 | "OverCurrentFailure", 148 | "OverVoltage", 149 | "PowerMeterFailure", 150 | "PowerSwitchFailure", 151 | "ReaderFailure", 152 | "ResetFailure", 153 | "UnderVoltage", 154 | "WeakSignal" 155 | }; 156 | 157 | enum RemoteStartStopStatus { 158 | REMOTE_STATUS_UNDEFINED = 0, 159 | REMOTE_STATUS_ACCEPTED = 1, 160 | REMOTE_STATUS_REJECTED = 2 161 | }; 162 | static const string RemoteStartStopStatusNames[3] = { 163 | "Undefined", 164 | "Accepted", 165 | "Rejected" 166 | }; 167 | 168 | enum AuthorizationStatus { 169 | AUTH_STATUS_UNDEFINED = 0, 170 | AUTH_STATUS_ACCEPTED, 171 | AUTH_STATUS_BLOCKED, 172 | AUTH_STATUS_EXPIRED, 173 | AUTH_STATUS_INVALID, 174 | AUTH_STATUS_CONCURRENTTX 175 | }; 176 | 177 | static std::map AuthorizationStatusMap = { 178 | {"Accepted", AUTH_STATUS_ACCEPTED}, 179 | {"Blocked", AUTH_STATUS_BLOCKED}, 180 | {"Expired", AUTH_STATUS_EXPIRED}, 181 | {"Invalid", AUTH_STATUS_INVALID}, 182 | {"ConcurrentTx", AUTH_STATUS_CONCURRENTTX} 183 | }; 184 | 185 | enum StopTransactionReason { 186 | STOP_TRANS_UNDEFINED = 0, 187 | STOP_TRANS_DEAUTHORIZED, 188 | STOP_TRANS_EMERGENCY_STOP, 189 | STOP_TRANS_EVDISCONNECTED, 190 | STOP_TRANS_HARDRESET, 191 | STOP_TRANS_LOCAL, 192 | STOP_TRANS_OTHER, 193 | STOP_TRANS_POWERLOSS, 194 | STOP_TRANS_REBOOT, 195 | STOP_TRANS_REMOTE, 196 | STOP_TRANS_SOFTRESET, 197 | STOP_TRANS_UNLOCKCOMMAND 198 | }; 199 | 200 | static const string StopTransactionReasonNames[12] = { 201 | "Undefined", 202 | "DeAuthorized", 203 | "EmergencyStop", 204 | "EVDisconnected", 205 | "HardReset", 206 | "Local", 207 | "Other", 208 | "PowerLoss", 209 | "Reboot", 210 | "Remote", 211 | "SoftReset", 212 | "UnlockCommand" 213 | }; -------------------------------------------------------------------------------- /include/rtc.h: -------------------------------------------------------------------------------- 1 | #include 2 | #include "RTClib.h" 3 | #include 4 | void update_rtc(); 5 | void init_rtc(); 6 | bool adjust_rtc(string dateTime); 7 | string get_datetime_rtc(); -------------------------------------------------------------------------------- /lib/README: -------------------------------------------------------------------------------- 1 | 2 | This directory is intended for project specific (private) libraries. 3 | PlatformIO will compile them to static libraries and link into executable file. 4 | 5 | The source code of each library should be placed in a an own separate directory 6 | ("lib/your_library_name/[here are source files]"). 7 | 8 | For example, see a structure of the following two libraries `Foo` and `Bar`: 9 | 10 | |--lib 11 | | | 12 | | |--Bar 13 | | | |--docs 14 | | | |--examples 15 | | | |--src 16 | | | |- Bar.c 17 | | | |- Bar.h 18 | | | |- library.json (optional, custom build options, etc) https://docs.platformio.org/page/librarymanager/config.html 19 | | | 20 | | |--Foo 21 | | | |- Foo.c 22 | | | |- Foo.h 23 | | | 24 | | |- README --> THIS FILE 25 | | 26 | |- platformio.ini 27 | |--src 28 | |- main.c 29 | 30 | and a contents of `src/main.c`: 31 | ``` 32 | #include 33 | #include 34 | 35 | int main (void) 36 | { 37 | ... 38 | } 39 | 40 | ``` 41 | 42 | PlatformIO Library Dependency Finder will find automatically dependent 43 | libraries scanning project source files. 44 | 45 | More information about PlatformIO Library Dependency Finder 46 | - https://docs.platformio.org/page/librarymanager/ldf.html 47 | -------------------------------------------------------------------------------- /lib/RTClib-master/.github/ISSUE_TEMPLATE.md: -------------------------------------------------------------------------------- 1 | Thank you for opening an issue on an Adafruit Arduino library repository. To 2 | improve the speed of resolution please review the following guidelines and 3 | common troubleshooting steps below before creating the issue: 4 | 5 | - **Do not use GitHub issues for troubleshooting projects and issues.** Instead use 6 | the forums at http://forums.adafruit.com to ask questions and troubleshoot why 7 | something isn't working as expected. In many cases the problem is a common issue 8 | that you will more quickly receive help from the forum community. GitHub issues 9 | are meant for known defects in the code. If you don't know if there is a defect 10 | in the code then start with troubleshooting on the forum first. 11 | 12 | - **If following a tutorial or guide be sure you didn't miss a step.** Carefully 13 | check all of the steps and commands to run have been followed. Consult the 14 | forum if you're unsure or have questions about steps in a guide/tutorial. 15 | 16 | - **For Arduino projects check these very common issues to ensure they don't apply**: 17 | 18 | - For uploading sketches or communicating with the board make sure you're using 19 | a **USB data cable** and **not** a **USB charge-only cable**. It is sometimes 20 | very hard to tell the difference between a data and charge cable! Try using the 21 | cable with other devices or swapping to another cable to confirm it is not 22 | the problem. 23 | 24 | - **Be sure you are supplying adequate power to the board.** Check the specs of 25 | your board and plug in an external power supply. In many cases just 26 | plugging a board into your computer is not enough to power it and other 27 | peripherals. 28 | 29 | - **Double check all soldering joints and connections.** Flakey connections 30 | cause many mysterious problems. See the [guide to excellent soldering](https://learn.adafruit.com/adafruit-guide-excellent-soldering/tools) for examples of good solder joints. 31 | 32 | - **Ensure you are using an official Arduino or Adafruit board.** We can't 33 | guarantee a clone board will have the same functionality and work as expected 34 | with this code and don't support them. 35 | 36 | If you're sure this issue is a defect in the code and checked the steps above 37 | please fill in the following fields to provide enough troubleshooting information. 38 | You may delete the guideline and text above to just leave the following details: 39 | 40 | - Arduino board: **INSERT ARDUINO BOARD NAME/TYPE HERE** 41 | 42 | - Arduino IDE version (found in Arduino -> About Arduino menu): **INSERT ARDUINO 43 | VERSION HERE** 44 | 45 | - List the steps to reproduce the problem below (if possible attach a sketch or 46 | copy the sketch code in too): **LIST REPRO STEPS BELOW** 47 | -------------------------------------------------------------------------------- /lib/RTClib-master/.github/PULL_REQUEST_TEMPLATE.md: -------------------------------------------------------------------------------- 1 | Thank you for creating a pull request to contribute to Adafruit's GitHub code! 2 | Before you open the request please review the following guidelines and tips to 3 | help it be more easily integrated: 4 | 5 | - **Describe the scope of your change--i.e. what the change does and what parts 6 | of the code were modified.** This will help us understand any risks of integrating 7 | the code. 8 | 9 | - **Describe any known limitations with your change.** For example if the change 10 | doesn't apply to a supported platform of the library please mention it. 11 | 12 | - **Please run any tests or examples that can exercise your modified code.** We 13 | strive to not break users of the code and running tests/examples helps with this 14 | process. 15 | 16 | Thank you again for contributing! We will try to test and integrate the change 17 | as soon as we can, but be aware we have many GitHub repositories to manage and 18 | can't immediately respond to every request. There is no need to bump or check in 19 | on a pull request (it will clutter the discussion of the request). 20 | 21 | Also don't be worried if the request is closed or not integrated--sometimes the 22 | priorities of Adafruit's GitHub code (education, ease of use) might not match the 23 | priorities of the pull request. Don't fret, the open source community thrives on 24 | forks and GitHub makes it easy to keep your changes in a forked repo. 25 | 26 | After reviewing the guidelines above you can delete this text from the pull request. 27 | -------------------------------------------------------------------------------- /lib/RTClib-master/.github/workflows/githubci.yml: -------------------------------------------------------------------------------- 1 | name: Arduino Library CI 2 | 3 | on: [pull_request, push, repository_dispatch] 4 | 5 | jobs: 6 | build: 7 | runs-on: ubuntu-latest 8 | 9 | steps: 10 | - uses: actions/setup-python@v1 11 | with: 12 | python-version: '3.x' 13 | - uses: actions/checkout@v2 14 | - uses: actions/checkout@v2 15 | with: 16 | repository: adafruit/ci-arduino 17 | path: ci 18 | 19 | - name: pre-install 20 | run: bash ci/actions_install.sh 21 | 22 | - name: test platforms 23 | run: python3 ci/build_platform.py main_platforms 24 | 25 | - name: clang 26 | run: python3 ci/run-clang-format.py -e "ci/*" -e "bin/*" -r . 27 | 28 | - name: doxygen 29 | env: 30 | GH_REPO_TOKEN: ${{ secrets.GH_REPO_TOKEN }} 31 | PRETTYNAME : "RTClib" 32 | run: bash ci/doxy_gen_and_deploy.sh 33 | -------------------------------------------------------------------------------- /lib/RTClib-master/.gitignore: -------------------------------------------------------------------------------- 1 | *~ 2 | html 3 | Doxyfile* 4 | doxygen_sqlite3.db 5 | -------------------------------------------------------------------------------- /lib/RTClib-master/README.md: -------------------------------------------------------------------------------- 1 | # RTClib [![Build Status](https://github.com/adafruit/RTClib/workflows/Arduino%20Library%20CI/badge.svg)](https://github.com/adafruit/RTClib/actions)[![Documentation](https://github.com/adafruit/ci-arduino/blob/master/assets/doxygen_badge.svg)](http://adafruit.github.io/RTClib/html/index.html) 2 | 3 | This is a fork of JeeLab's fantastic real time clock library for Arduino. 4 | 5 | Works great with Adafruit RTC breakouts: 6 | 7 | - [DS3231 Precision RTC](https://www.adafruit.com/product/3013) 8 | - [PCF8523 RTC](https://www.adafruit.com/product/3295) 9 | - [DS1307 RTC](https://www.adafruit.com/product/3296) 10 | 11 | Please note that dayOfTheWeek() ranges from 0 to 6 inclusive with 0 being 'Sunday'. 12 | 13 | 14 | 15 | ## Compatibility 16 | 17 | MCU | Tested Works | Doesn't Work | Not Tested | Notes 18 | ------------------ | :----------: | :----------: | :---------: | ----- 19 | Atmega328 @ 16MHz | X | | | 20 | Atmega328 @ 12MHz | X | | | 21 | Atmega32u4 @ 16MHz | X | | | Use SDA/SCL on pins D3 & D2 22 | Atmega32u4 @ 8MHz | X | | | Use SDA/SCL on pins D3 & D2 23 | ESP8266 | X | | | SDA/SCL default to pins 4 & 5 but any two pins can be assigned as SDA/SCL using Wire.begin(SDA,SCL) 24 | Atmega2560 @ 16MHz | X | | | Use SDA/SCL on Pins 20 & 21 25 | ATSAM3X8E | X | | | Use SDA1 and SCL1 26 | ATSAM21D | X | | | 27 | ATtiny85 @ 16MHz | X | | | 28 | ATtiny85 @ 8MHz | X | | | 29 | Intel Curie @ 32MHz | | | X | 30 | STM32F2 | | | X | 31 | 32 | * ATmega328 @ 16MHz : Arduino UNO, Adafruit Pro Trinket 5V, Adafruit Metro 328, Adafruit Metro Mini 33 | * ATmega328 @ 12MHz : Adafruit Pro Trinket 3V 34 | * ATmega32u4 @ 16MHz : Arduino Leonardo, Arduino Micro, Arduino Yun, Teensy 2.0 35 | * ATmega32u4 @ 8MHz : Adafruit Flora, Bluefruit Micro 36 | * ESP8266 : Adafruit Huzzah 37 | * ATmega2560 @ 16MHz : Arduino Mega 38 | * ATSAM3X8E : Arduino Due 39 | * ATSAM21D : Arduino Zero, M0 Pro 40 | * ATtiny85 @ 16MHz : Adafruit Trinket 5V 41 | * ATtiny85 @ 8MHz : Adafruit Gemma, Arduino Gemma, Adafruit Trinket 3V 42 | 43 | 44 | Adafruit invests time and resources providing this open source code, please support Adafruit and open-source hardware by purchasing products from Adafruit! 45 | 46 | # Dependencies 47 | * [TinyWireM](https://github.com/adafruit/TinyWireM) 48 | 49 | # Contributing 50 | 51 | Contributions are welcome! Please read our [Code of Conduct](https://github.com/adafruit/RTClib/blob/master/code-of-conduct.md) 52 | before contributing to help this project stay welcoming. 53 | 54 | ## Documentation and doxygen 55 | For the detailed API documentation, see https://adafruit.github.io/RTClib/html/index.html 56 | Documentation is produced by doxygen. Contributions should include documentation for any new code added. 57 | 58 | Some examples of how to use doxygen can be found in these guide pages: 59 | 60 | https://learn.adafruit.com/the-well-automated-arduino-library/doxygen 61 | 62 | https://learn.adafruit.com/the-well-automated-arduino-library/doxygen-tips 63 | 64 | ## Code formatting and clang-format 65 | The code should be formatted according to the [LLVM Coding Standards](https://llvm.org/docs/CodingStandards.html), which is the default of the clang-format tool. The easiest way to ensure conformance is to [install clang-format](https://llvm.org/builds/) and run 66 | 67 | ```shell 68 | clang-format -i ` 69 | ``` 70 | 71 | Written by JeeLabs 72 | MIT license, check license.txt for more information 73 | All text above must be included in any redistribution 74 | 75 | To install, use the Arduino Library Manager and search for "RTClib" and install the library. 76 | -------------------------------------------------------------------------------- /lib/RTClib-master/RTClib.h: -------------------------------------------------------------------------------- 1 | /**************************************************************************/ 2 | /*! 3 | @file RTClib.h 4 | 5 | Original library by JeeLabs http://news.jeelabs.org/code/, released to the 6 | public domain 7 | 8 | License: MIT (see LICENSE) 9 | 10 | This is a fork of JeeLab's fantastic real time clock library for Arduino. 11 | 12 | For details on using this library with an RTC module like the DS1307, PCF8523, 13 | or DS3231, see the guide at: 14 | https://learn.adafruit.com/ds1307-real-time-clock-breakout-board-kit/overview 15 | 16 | Adafruit invests time and resources providing this open source code, 17 | please support Adafruit and open-source hardware by purchasing 18 | products from Adafruit! 19 | */ 20 | /**************************************************************************/ 21 | 22 | #ifndef _RTCLIB_H_ 23 | #define _RTCLIB_H_ 24 | 25 | #include 26 | #include 27 | using std::string; 28 | class TimeSpan; 29 | class __FlashStringHelper; 30 | /** Registers */ 31 | #define PCF8523_ADDRESS 0x68 ///< I2C address for PCF8523 32 | #define PCF8523_CLKOUTCONTROL 0x0F ///< Timer and CLKOUT control register 33 | #define PCF8523_CONTROL_1 0x00 ///< Control and status register 1 34 | #define PCF8523_CONTROL_2 0x01 ///< Control and status register 2 35 | #define PCF8523_CONTROL_3 0x02 ///< Control and status register 3 36 | #define PCF8523_TIMER_B_FRCTL 0x12 ///< Timer B source clock frequency control 37 | #define PCF8523_TIMER_B_VALUE 0x13 ///< Timer B value (number clock periods) 38 | #define PCF8523_OFFSET 0x0E ///< Offset register 39 | #define PCF8523_STATUSREG 0x03 ///< Status register 40 | 41 | #define PCF8563_ADDRESS 0x51 ///< I2C address for PCF8563 42 | #define PCF8563_CLKOUTCONTROL 0x0D ///< CLKOUT control register 43 | #define PCF8563_CONTROL_1 0x00 ///< Control and status register 1 44 | #define PCF8563_CONTROL_2 0x01 ///< Control and status register 2 45 | #define PCF8563_VL_SECONDS 0x02 ///< register address for VL_SECONDS 46 | #define PCF8563_CLKOUT_MASK 0x83 ///< bitmask for SqwPinMode on CLKOUT pin 47 | 48 | #define DS1307_ADDRESS 0x68 ///< I2C address for DS1307 49 | #define DS1307_CONTROL 0x07 ///< Control register 50 | #define DS1307_NVRAM 0x08 ///< Start of RAM registers - 56 bytes, 0x08 to 0x3f 51 | 52 | #define DS3231_ADDRESS 0x68 ///< I2C address for DS3231 53 | #define DS3231_TIME 0x00 ///< Time register 54 | #define DS3231_ALARM1 0x07 ///< Alarm 1 register 55 | #define DS3231_ALARM2 0x0B ///< Alarm 2 register 56 | #define DS3231_CONTROL 0x0E ///< Control register 57 | #define DS3231_STATUSREG 0x0F ///< Status register 58 | #define DS3231_TEMPERATUREREG \ 59 | 0x11 ///< Temperature register (high byte - low byte is at 0x12), 10-bit 60 | ///< temperature value 61 | 62 | /** Constants */ 63 | #define SECONDS_PER_DAY 86400L ///< 60 * 60 * 24 64 | #define SECONDS_FROM_1970_TO_2000 \ 65 | 946684800 ///< Unixtime for 2000-01-01 00:00:00, useful for initialization 66 | 67 | /**************************************************************************/ 68 | /*! 69 | @brief Simple general-purpose date/time class (no TZ / DST / leap 70 | seconds). 71 | 72 | This class stores date and time information in a broken-down form, as a 73 | tuple (year, month, day, hour, minute, second). The day of the week is 74 | not stored, but computed on request. The class has no notion of time 75 | zones, daylight saving time, or 76 | [leap seconds](http://en.wikipedia.org/wiki/Leap_second): time is stored 77 | in whatever time zone the user chooses to use. 78 | 79 | The class supports dates in the range from 1 Jan 2000 to 31 Dec 2099 80 | inclusive. 81 | */ 82 | /**************************************************************************/ 83 | class DateTime { 84 | public: 85 | DateTime(uint32_t t = SECONDS_FROM_1970_TO_2000); 86 | DateTime(uint16_t year, uint8_t month, uint8_t day, uint8_t hour = 0, 87 | uint8_t min = 0, uint8_t sec = 0); 88 | DateTime(const DateTime ©); 89 | DateTime(const char *date, const char *time); 90 | DateTime(const __FlashStringHelper *date, const __FlashStringHelper *time); 91 | DateTime(const char *iso8601date); 92 | bool isValid() const; 93 | char *toString(char *buffer); 94 | 95 | /*! 96 | @brief Return the year. 97 | @return Year (range: 2000--2099). 98 | */ 99 | uint16_t year() const { return 2000U + yOff; } 100 | /*! 101 | @brief Return the month. 102 | @return Month number (1--12). 103 | */ 104 | uint8_t month() const { return m; } 105 | /*! 106 | @brief Return the day of the month. 107 | @return Day of the month (1--31). 108 | */ 109 | uint8_t day() const { return d; } 110 | /*! 111 | @brief Return the hour 112 | @return Hour (0--23). 113 | */ 114 | uint8_t hour() const { return hh; } 115 | 116 | uint8_t twelveHour() const; 117 | /*! 118 | @brief Return whether the time is PM. 119 | @return 0 if the time is AM, 1 if it's PM. 120 | */ 121 | uint8_t isPM() const { return hh >= 12; } 122 | /*! 123 | @brief Return the minute. 124 | @return Minute (0--59). 125 | */ 126 | uint8_t minute() const { return mm; } 127 | /*! 128 | @brief Return the second. 129 | @return Second (0--59). 130 | */ 131 | uint8_t second() const { return ss; } 132 | 133 | uint8_t dayOfTheWeek() const; 134 | 135 | /* 32-bit times as seconds since 2000-01-01. */ 136 | uint32_t secondstime() const; 137 | 138 | /* 32-bit times as seconds since 1970-01-01. */ 139 | uint32_t unixtime(void) const; 140 | 141 | /*! 142 | Format of the ISO 8601 timestamp generated by `timestamp()`. Each 143 | option corresponds to a `toString()` format as follows: 144 | */ 145 | enum timestampOpt { 146 | TIMESTAMP_FULL, //!< `YYYY-MM-DDThh:mm:ss` 147 | TIMESTAMP_TIME, //!< `hh:mm:ss` 148 | TIMESTAMP_DATE //!< `YYYY-MM-DD` 149 | }; 150 | string timestamp(timestampOpt opt = TIMESTAMP_FULL); 151 | 152 | DateTime operator+(const TimeSpan &span); 153 | DateTime operator-(const TimeSpan &span); 154 | TimeSpan operator-(const DateTime &right); 155 | bool operator<(const DateTime &right) const; 156 | 157 | /*! 158 | @brief Test if one DateTime is greater (later) than another. 159 | @warning if one or both DateTime objects are invalid, returned value is 160 | meaningless 161 | @see use `isValid()` method to check if DateTime object is valid 162 | @param right DateTime object to compare 163 | @return True if the left DateTime is later than the right one, 164 | false otherwise 165 | */ 166 | bool operator>(const DateTime &right) const { return right < *this; } 167 | 168 | /*! 169 | @brief Test if one DateTime is less (earlier) than or equal to another 170 | @warning if one or both DateTime objects are invalid, returned value is 171 | meaningless 172 | @see use `isValid()` method to check if DateTime object is valid 173 | @param right DateTime object to compare 174 | @return True if the left DateTime is earlier than or equal to the 175 | right one, false otherwise 176 | */ 177 | bool operator<=(const DateTime &right) const { return !(*this > right); } 178 | 179 | /*! 180 | @brief Test if one DateTime is greater (later) than or equal to another 181 | @warning if one or both DateTime objects are invalid, returned value is 182 | meaningless 183 | @see use `isValid()` method to check if DateTime object is valid 184 | @param right DateTime object to compare 185 | @return True if the left DateTime is later than or equal to the right 186 | one, false otherwise 187 | */ 188 | bool operator>=(const DateTime &right) const { return !(*this < right); } 189 | bool operator==(const DateTime &right) const; 190 | 191 | /*! 192 | @brief Test if two DateTime objects are not equal. 193 | @warning if one or both DateTime objects are invalid, returned value is 194 | meaningless 195 | @see use `isValid()` method to check if DateTime object is valid 196 | @param right DateTime object to compare 197 | @return True if the two objects are not equal, false if they are 198 | */ 199 | bool operator!=(const DateTime &right) const { return !(*this == right); } 200 | 201 | protected: 202 | uint8_t yOff; ///< Year offset from 2000 203 | uint8_t m; ///< Month 1-12 204 | uint8_t d; ///< Day 1-31 205 | uint8_t hh; ///< Hours 0-23 206 | uint8_t mm; ///< Minutes 0-59 207 | uint8_t ss; ///< Seconds 0-59 208 | }; 209 | 210 | /**************************************************************************/ 211 | /*! 212 | @brief Timespan which can represent changes in time with seconds accuracy. 213 | */ 214 | /**************************************************************************/ 215 | class TimeSpan { 216 | public: 217 | TimeSpan(int32_t seconds = 0); 218 | TimeSpan(int16_t days, int8_t hours, int8_t minutes, int8_t seconds); 219 | TimeSpan(const TimeSpan ©); 220 | 221 | /*! 222 | @brief Number of days in the TimeSpan 223 | e.g. 4 224 | @return int16_t days 225 | */ 226 | int16_t days() const { return _seconds / 86400L; } 227 | /*! 228 | @brief Number of hours in the TimeSpan 229 | This is not the total hours, it includes the days 230 | e.g. 4 days, 3 hours - NOT 99 hours 231 | @return int8_t hours 232 | */ 233 | int8_t hours() const { return _seconds / 3600 % 24; } 234 | /*! 235 | @brief Number of minutes in the TimeSpan 236 | This is not the total minutes, it includes days/hours 237 | e.g. 4 days, 3 hours, 27 minutes 238 | @return int8_t minutes 239 | */ 240 | int8_t minutes() const { return _seconds / 60 % 60; } 241 | /*! 242 | @brief Number of seconds in the TimeSpan 243 | This is not the total seconds, it includes the days/hours/minutes 244 | e.g. 4 days, 3 hours, 27 minutes, 7 seconds 245 | @return int8_t seconds 246 | */ 247 | int8_t seconds() const { return _seconds % 60; } 248 | /*! 249 | @brief Total number of seconds in the TimeSpan, e.g. 358027 250 | @return int32_t seconds 251 | */ 252 | int32_t totalseconds() const { return _seconds; } 253 | 254 | TimeSpan operator+(const TimeSpan &right); 255 | TimeSpan operator-(const TimeSpan &right); 256 | 257 | protected: 258 | int32_t _seconds; ///< Actual TimeSpan value is stored as seconds 259 | }; 260 | 261 | /** DS1307 SQW pin mode settings */ 262 | enum Ds1307SqwPinMode { 263 | DS1307_OFF = 0x00, // Low 264 | DS1307_ON = 0x80, // High 265 | DS1307_SquareWave1HZ = 0x10, // 1Hz square wave 266 | DS1307_SquareWave4kHz = 0x11, // 4kHz square wave 267 | DS1307_SquareWave8kHz = 0x12, // 8kHz square wave 268 | DS1307_SquareWave32kHz = 0x13 // 32kHz square wave 269 | }; 270 | 271 | /**************************************************************************/ 272 | /*! 273 | @brief RTC based on the DS1307 chip connected via I2C and the Wire library 274 | */ 275 | /**************************************************************************/ 276 | class RTC_DS1307 { 277 | public: 278 | bool begin(void); 279 | static void adjust(const DateTime &dt); 280 | uint8_t isrunning(void); 281 | static DateTime now(); 282 | static Ds1307SqwPinMode readSqwPinMode(); 283 | static void writeSqwPinMode(Ds1307SqwPinMode mode); 284 | uint8_t readnvram(uint8_t address); 285 | void readnvram(uint8_t *buf, uint8_t size, uint8_t address); 286 | void writenvram(uint8_t address, uint8_t data); 287 | void writenvram(uint8_t address, uint8_t *buf, uint8_t size); 288 | }; 289 | 290 | /** DS3231 SQW pin mode settings */ 291 | enum Ds3231SqwPinMode { 292 | DS3231_OFF = 0x1C, /**< Off */ 293 | DS3231_SquareWave1Hz = 0x00, /**< 1Hz square wave */ 294 | DS3231_SquareWave1kHz = 0x08, /**< 1kHz square wave */ 295 | DS3231_SquareWave4kHz = 0x10, /**< 4kHz square wave */ 296 | DS3231_SquareWave8kHz = 0x18 /**< 8kHz square wave */ 297 | }; 298 | 299 | /** DS3231 Alarm modes for alarm 1 */ 300 | enum Ds3231Alarm1Mode { 301 | DS3231_A1_PerSecond = 0x0F, /**< Alarm once per second */ 302 | DS3231_A1_Second = 0x0E, /**< Alarm when seconds match */ 303 | DS3231_A1_Minute = 0x0C, /**< Alarm when minutes and seconds match */ 304 | DS3231_A1_Hour = 0x08, /**< Alarm when hours, minutes 305 | and seconds match */ 306 | DS3231_A1_Date = 0x00, /**< Alarm when date (day of month), hours, 307 | minutes and seconds match */ 308 | DS3231_A1_Day = 0x10 /**< Alarm when day (day of week), hours, 309 | minutes and seconds match */ 310 | }; 311 | /** DS3231 Alarm modes for alarm 2 */ 312 | enum Ds3231Alarm2Mode { 313 | DS3231_A2_PerMinute = 0x7, /**< Alarm once per minute 314 | (whenever seconds are 0) */ 315 | DS3231_A2_Minute = 0x6, /**< Alarm when minutes match */ 316 | DS3231_A2_Hour = 0x4, /**< Alarm when hours and minutes match */ 317 | DS3231_A2_Date = 0x0, /**< Alarm when date (day of month), hours 318 | and minutes match */ 319 | DS3231_A2_Day = 0x8 /**< Alarm when day (day of week), hours 320 | and minutes match */ 321 | }; 322 | 323 | /**************************************************************************/ 324 | /*! 325 | @brief RTC based on the DS3231 chip connected via I2C and the Wire library 326 | */ 327 | /**************************************************************************/ 328 | class RTC_DS3231 { 329 | public: 330 | bool begin(uint8_t sda, uint8_t scl); 331 | static int adjust(const DateTime &dt); 332 | bool lostPower(void); 333 | static DateTime now(); 334 | static Ds3231SqwPinMode readSqwPinMode(); 335 | static void writeSqwPinMode(Ds3231SqwPinMode mode); 336 | bool setAlarm1(const DateTime &dt, Ds3231Alarm1Mode alarm_mode); 337 | bool setAlarm2(const DateTime &dt, Ds3231Alarm2Mode alarm_mode); 338 | void disableAlarm(uint8_t alarm_num); 339 | void clearAlarm(uint8_t alarm_num); 340 | bool alarmFired(uint8_t alarm_num); 341 | void enable32K(void); 342 | void disable32K(void); 343 | bool isEnabled32K(void); 344 | static float getTemperature(); // in Celsius degree 345 | }; 346 | 347 | /** PCF8523 INT/SQW pin mode settings */ 348 | enum Pcf8523SqwPinMode { 349 | PCF8523_OFF = 7, /**< Off */ 350 | PCF8523_SquareWave1HZ = 6, /**< 1Hz square wave */ 351 | PCF8523_SquareWave32HZ = 5, /**< 32Hz square wave */ 352 | PCF8523_SquareWave1kHz = 4, /**< 1kHz square wave */ 353 | PCF8523_SquareWave4kHz = 3, /**< 4kHz square wave */ 354 | PCF8523_SquareWave8kHz = 2, /**< 8kHz square wave */ 355 | PCF8523_SquareWave16kHz = 1, /**< 16kHz square wave */ 356 | PCF8523_SquareWave32kHz = 0 /**< 32kHz square wave */ 357 | }; 358 | 359 | /** PCF8523 Timer Source Clock Frequencies for Timers A and B */ 360 | enum PCF8523TimerClockFreq { 361 | PCF8523_Frequency4kHz = 0, /**< 1/4096th second = 244 microseconds, 362 | max 62.256 milliseconds */ 363 | PCF8523_Frequency64Hz = 1, /**< 1/64th second = 15.625 milliseconds, 364 | max 3.984375 seconds */ 365 | PCF8523_FrequencySecond = 2, /**< 1 second, max 255 seconds = 4.25 minutes */ 366 | PCF8523_FrequencyMinute = 3, /**< 1 minute, max 255 minutes = 4.25 hours */ 367 | PCF8523_FrequencyHour = 4, /**< 1 hour, max 255 hours = 10.625 days */ 368 | }; 369 | 370 | /** PCF8523 Timer Interrupt Low Pulse Width options for Timer B only */ 371 | enum PCF8523TimerIntPulse { 372 | PCF8523_LowPulse3x64Hz = 0, /**< 46.875 ms 3/64ths second */ 373 | PCF8523_LowPulse4x64Hz = 1, /**< 62.500 ms 4/64ths second */ 374 | PCF8523_LowPulse5x64Hz = 2, /**< 78.125 ms 5/64ths second */ 375 | PCF8523_LowPulse6x64Hz = 3, /**< 93.750 ms 6/64ths second */ 376 | PCF8523_LowPulse8x64Hz = 4, /**< 125.000 ms 8/64ths second */ 377 | PCF8523_LowPulse10x64Hz = 5, /**< 156.250 ms 10/64ths second */ 378 | PCF8523_LowPulse12x64Hz = 6, /**< 187.500 ms 12/64ths second */ 379 | PCF8523_LowPulse14x64Hz = 7 /**< 218.750 ms 14/64ths second */ 380 | }; 381 | 382 | /** PCF8523 Offset modes for making temperature/aging/accuracy adjustments */ 383 | enum Pcf8523OffsetMode { 384 | PCF8523_TwoHours = 0x00, /**< Offset made every two hours */ 385 | PCF8523_OneMinute = 0x80 /**< Offset made every minute */ 386 | }; 387 | 388 | /**************************************************************************/ 389 | /*! 390 | @brief RTC based on the PCF8523 chip connected via I2C and the Wire library 391 | */ 392 | /**************************************************************************/ 393 | class RTC_PCF8523 { 394 | public: 395 | bool begin(void); 396 | void adjust(const DateTime &dt); 397 | bool lostPower(void); 398 | bool initialized(void); 399 | static DateTime now(); 400 | void start(void); 401 | void stop(void); 402 | uint8_t isrunning(); 403 | Pcf8523SqwPinMode readSqwPinMode(); 404 | void writeSqwPinMode(Pcf8523SqwPinMode mode); 405 | void enableSecondTimer(void); 406 | void disableSecondTimer(void); 407 | void enableCountdownTimer(PCF8523TimerClockFreq clkFreq, uint8_t numPeriods, 408 | uint8_t lowPulseWidth); 409 | void enableCountdownTimer(PCF8523TimerClockFreq clkFreq, uint8_t numPeriods); 410 | void disableCountdownTimer(void); 411 | void deconfigureAllTimers(void); 412 | void calibrate(Pcf8523OffsetMode mode, int8_t offset); 413 | }; 414 | 415 | /** PCF8563 CLKOUT pin mode settings */ 416 | enum Pcf8563SqwPinMode { 417 | PCF8563_SquareWaveOFF = 0x00, /**< Off */ 418 | PCF8563_SquareWave1Hz = 0x83, /**< 1Hz square wave */ 419 | PCF8563_SquareWave32Hz = 0x82, /**< 32Hz square wave */ 420 | PCF8563_SquareWave1kHz = 0x81, /**< 1kHz square wave */ 421 | PCF8563_SquareWave32kHz = 0x80 /**< 32kHz square wave */ 422 | }; 423 | 424 | /**************************************************************************/ 425 | /*! 426 | @brief RTC based on the PCF8563 chip connected via I2C and the Wire library 427 | */ 428 | /**************************************************************************/ 429 | 430 | class RTC_PCF8563 { 431 | public: 432 | bool begin(void); 433 | bool lostPower(void); 434 | void adjust(const DateTime &dt); 435 | static DateTime now(); 436 | void start(void); 437 | void stop(void); 438 | uint8_t isrunning(); 439 | Pcf8563SqwPinMode readSqwPinMode(); 440 | void writeSqwPinMode(Pcf8563SqwPinMode mode); 441 | }; 442 | 443 | /**************************************************************************/ 444 | /*! 445 | @brief RTC using the internal millis() clock, has to be initialized before 446 | use. NOTE: this is immune to millis() rollover events. 447 | */ 448 | /**************************************************************************/ 449 | class RTC_Millis { 450 | public: 451 | /*! 452 | @brief Start the RTC 453 | @param dt DateTime object with the date/time to set 454 | */ 455 | static void begin(const DateTime &dt) { adjust(dt); } 456 | static void adjust(const DateTime &dt); 457 | static DateTime now(); 458 | 459 | protected: 460 | static uint32_t lastUnix; ///< Unix time from the previous call to now() - 461 | ///< prevents rollover issues 462 | static uint32_t lastMillis; ///< the millis() value corresponding to the last 463 | ///< **full second** of Unix time 464 | }; 465 | 466 | /**************************************************************************/ 467 | /*! 468 | @brief RTC using the internal micros() clock, has to be initialized before 469 | use. Unlike RTC_Millis, this can be tuned in order to compensate for 470 | the natural drift of the system clock. Note that now() has to be 471 | called more frequently than the micros() rollover period, which is 472 | approximately 71.6 minutes. 473 | */ 474 | /**************************************************************************/ 475 | class RTC_Micros { 476 | public: 477 | /*! 478 | @brief Start the RTC 479 | @param dt DateTime object with the date/time to set 480 | */ 481 | static void begin(const DateTime &dt) { adjust(dt); } 482 | static void adjust(const DateTime &dt); 483 | static void adjustDrift(int ppm); 484 | static DateTime now(); 485 | 486 | protected: 487 | static uint32_t microsPerSecond; ///< Number of microseconds reported by 488 | ///< micros() per "true" (calibrated) second 489 | static uint32_t lastUnix; ///< Unix time from the previous call to now() - 490 | ///< prevents rollover issues 491 | static uint32_t lastMicros; ///< micros() value corresponding to the last full 492 | ///< second of Unix time 493 | }; 494 | 495 | #endif // _RTCLIB_H_ 496 | -------------------------------------------------------------------------------- /lib/RTClib-master/code-of-conduct.md: -------------------------------------------------------------------------------- 1 | # Adafruit Community Code of Conduct 2 | 3 | ## Our Pledge 4 | 5 | In the interest of fostering an open and welcoming environment, we as 6 | contributors and leaders pledge to making participation in our project and 7 | our community a harassment-free experience for everyone, regardless of age, body 8 | size, disability, ethnicity, gender identity and expression, level or type of 9 | experience, education, socio-economic status, nationality, personal appearance, 10 | race, religion, or sexual identity and orientation. 11 | 12 | ## Our Standards 13 | 14 | We are committed to providing a friendly, safe and welcoming environment for 15 | all. 16 | 17 | Examples of behavior that contributes to creating a positive environment 18 | include: 19 | 20 | * Be kind and courteous to others 21 | * Using welcoming and inclusive language 22 | * Being respectful of differing viewpoints and experiences 23 | * Collaborating with other community members 24 | * Gracefully accepting constructive criticism 25 | * Focusing on what is best for the community 26 | * Showing empathy towards other community members 27 | 28 | Examples of unacceptable behavior by participants include: 29 | 30 | * The use of sexualized language or imagery and sexual attention or advances 31 | * The use of inappropriate images, including in a community member's avatar 32 | * The use of inappropriate language, including in a community member's nickname 33 | * Any spamming, flaming, baiting or other attention-stealing behavior 34 | * Excessive or unwelcome helping; answering outside the scope of the question 35 | asked 36 | * Trolling, insulting/derogatory comments, and personal or political attacks 37 | * Public or private harassment 38 | * Publishing others' private information, such as a physical or electronic 39 | address, without explicit permission 40 | * Other conduct which could reasonably be considered inappropriate 41 | 42 | The goal of the standards and moderation guidelines outlined here is to build 43 | and maintain a respectful community. We ask that you don’t just aim to be 44 | "technically unimpeachable", but rather try to be your best self. 45 | 46 | We value many things beyond technical expertise, including collaboration and 47 | supporting others within our community. Providing a positive experience for 48 | other community members can have a much more significant impact than simply 49 | providing the correct answer. 50 | 51 | ## Our Responsibilities 52 | 53 | Project leaders are responsible for clarifying the standards of acceptable 54 | behavior and are expected to take appropriate and fair corrective action in 55 | response to any instances of unacceptable behavior. 56 | 57 | Project leaders have the right and responsibility to remove, edit, or 58 | reject messages, comments, commits, code, issues, and other contributions 59 | that are not aligned to this Code of Conduct, or to ban temporarily or 60 | permanently any community member for other behaviors that they deem 61 | inappropriate, threatening, offensive, or harmful. 62 | 63 | ## Moderation 64 | 65 | Instances of behaviors that violate the Adafruit Community Code of Conduct 66 | may be reported by any member of the community. Community members are 67 | encouraged to report these situations, including situations they witness 68 | involving other community members. 69 | 70 | You may report in the following ways: 71 | 72 | In any situation, you may send an email to . 73 | 74 | On the Adafruit Discord, you may send an open message from any channel 75 | to all Community Helpers by tagging @community helpers. You may also send an 76 | open message from any channel, or a direct message to @kattni#1507, 77 | @tannewt#4653, @Dan Halbert#1614, @cater#2442, @sommersoft#0222, or 78 | @Andon#8175. 79 | 80 | Email and direct message reports will be kept confidential. 81 | 82 | In situations on Discord where the issue is particularly egregious, possibly 83 | illegal, requires immediate action, or violates the Discord terms of service, 84 | you should also report the message directly to Discord. 85 | 86 | These are the steps for upholding our community’s standards of conduct. 87 | 88 | 1. Any member of the community may report any situation that violates the 89 | Adafruit Community Code of Conduct. All reports will be reviewed and 90 | investigated. 91 | 2. If the behavior is an egregious violation, the community member who 92 | committed the violation may be banned immediately, without warning. 93 | 3. Otherwise, moderators will first respond to such behavior with a warning. 94 | 4. Moderators follow a soft "three strikes" policy - the community member may 95 | be given another chance, if they are receptive to the warning and change their 96 | behavior. 97 | 5. If the community member is unreceptive or unreasonable when warned by a 98 | moderator, or the warning goes unheeded, they may be banned for a first or 99 | second offense. Repeated offenses will result in the community member being 100 | banned. 101 | 102 | ## Scope 103 | 104 | This Code of Conduct and the enforcement policies listed above apply to all 105 | Adafruit Community venues. This includes but is not limited to any community 106 | spaces (both public and private), the entire Adafruit Discord server, and 107 | Adafruit GitHub repositories. Examples of Adafruit Community spaces include 108 | but are not limited to meet-ups, audio chats on the Adafruit Discord, or 109 | interaction at a conference. 110 | 111 | This Code of Conduct applies both within project spaces and in public spaces 112 | when an individual is representing the project or its community. As a community 113 | member, you are representing our community, and are expected to behave 114 | accordingly. 115 | 116 | ## Attribution 117 | 118 | This Code of Conduct is adapted from the [Contributor Covenant][homepage], 119 | version 1.4, available at 120 | , 121 | and the [Rust Code of Conduct](https://www.rust-lang.org/en-US/conduct.html). 122 | 123 | For other projects adopting the Adafruit Community Code of 124 | Conduct, please contact the maintainers of those projects for enforcement. 125 | If you wish to use this code of conduct for your own project, consider 126 | explicitly mentioning your moderation policy or making a copy with your 127 | own moderation policy so as to avoid confusion. 128 | -------------------------------------------------------------------------------- /lib/RTClib-master/examples/DS3231_alarm/DS3231_alarm.ino: -------------------------------------------------------------------------------- 1 | /* Example implementation of an alarm using DS3231 2 | * 3 | * VCC and GND of RTC should be connected to some power source 4 | * SDA, SCL of RTC should be connected to SDA, SCL of arduino 5 | * SQW should be connected to CLOCK_INTERRUPT_PIN 6 | * CLOCK_INTERRUPT_PIN needs to work with interrupts 7 | */ 8 | 9 | #include 10 | // #include 11 | 12 | RTC_DS3231 rtc; 13 | 14 | // the pin that is connected to SQW 15 | #define CLOCK_INTERRUPT_PIN 2 16 | 17 | void setup() { 18 | Serial.begin(9600); 19 | 20 | // initializing the rtc 21 | if(!rtc.begin()) { 22 | Serial.println("Couldn't find RTC!"); 23 | Serial.flush(); 24 | abort(); 25 | } 26 | 27 | if(rtc.lostPower()) { 28 | // this will adjust to the date and time at compilation 29 | rtc.adjust(DateTime(F(__DATE__), F(__TIME__))); 30 | } 31 | 32 | //we don't need the 32K Pin, so disable it 33 | rtc.disable32K(); 34 | 35 | // Making it so, that the alarm will trigger an interrupt 36 | pinMode(CLOCK_INTERRUPT_PIN, INPUT_PULLUP); 37 | attachInterrupt(digitalPinToInterrupt(CLOCK_INTERRUPT_PIN), onAlarm, FALLING); 38 | 39 | // set alarm 1, 2 flag to false (so alarm 1, 2 didn't happen so far) 40 | // if not done, this easily leads to problems, as both register aren't reset on reboot/recompile 41 | rtc.clearAlarm(1); 42 | rtc.clearAlarm(2); 43 | 44 | // stop oscillating signals at SQW Pin 45 | // otherwise setAlarm1 will fail 46 | rtc.writeSqwPinMode(DS3231_OFF); 47 | 48 | // turn off alarm 2 (in case it isn't off already) 49 | // again, this isn't done at reboot, so a previously set alarm could easily go overlooked 50 | rtc.disableAlarm(2); 51 | 52 | // schedule an alarm 10 seconds in the future 53 | if(!rtc.setAlarm1( 54 | rtc.now() + TimeSpan(10), 55 | DS3231_A1_Second // this mode triggers the alarm when the seconds match. See Doxygen for other options 56 | )) { 57 | Serial.println("Error, alarm wasn't set!"); 58 | }else { 59 | Serial.println("Alarm will happen in 10 seconds!"); 60 | } 61 | } 62 | 63 | void loop() { 64 | // print current time 65 | char date[10] = "hh:mm:ss"; 66 | rtc.now().toString(date); 67 | Serial.print(date); 68 | // the value at SQW-Pin (because of pullup 1 means no alarm) 69 | Serial.print(" SQW: "); 70 | Serial.print(digitalRead(CLOCK_INTERRUPT_PIN)); 71 | // whether a alarm happened happened 72 | Serial.print(" Alarm1: "); 73 | Serial.print(rtc.alarmFired(1)); 74 | // Serial.print(" Alarm2: "); 75 | // Serial.println(rtc.alarmFired(2)); 76 | // control register values (see https://datasheets.maximintegrated.com/en/ds/DS3231.pdf page 13) 77 | // Serial.print(" Control: 0b"); 78 | // Serial.println(read_i2c_register(DS3231_ADDRESS, DS3231_CONTROL), BIN); 79 | 80 | // resetting SQW and alarm 1 flag 81 | // using setAlarm1, the next alarm could now be configurated 82 | if(rtc.alarmFired(1)) { 83 | rtc.clearAlarm(1); 84 | Serial.println("Alarm cleared"); 85 | } 86 | 87 | delay(2000); 88 | } 89 | 90 | void onAlarm() { 91 | Serial.println("Alarm occured!"); 92 | } 93 | 94 | /*static uint8_t read_i2c_register(uint8_t addr, uint8_t reg) { 95 | Wire.beginTransmission(addr); 96 | Wire.write((byte)reg); 97 | Wire.endTransmission(); 98 | 99 | Wire.requestFrom(addr, (byte)1); 100 | return Wire.read(); 101 | }*/ 102 | -------------------------------------------------------------------------------- /lib/RTClib-master/examples/datecalc/datecalc.ino: -------------------------------------------------------------------------------- 1 | // Simple date conversions and calculations 2 | 3 | #include "RTClib.h" 4 | 5 | void showDate(const char* txt, const DateTime& dt) { 6 | Serial.print(txt); 7 | Serial.print(' '); 8 | Serial.print(dt.year(), DEC); 9 | Serial.print('/'); 10 | Serial.print(dt.month(), DEC); 11 | Serial.print('/'); 12 | Serial.print(dt.day(), DEC); 13 | Serial.print(' '); 14 | Serial.print(dt.hour(), DEC); 15 | Serial.print(':'); 16 | Serial.print(dt.minute(), DEC); 17 | Serial.print(':'); 18 | Serial.print(dt.second(), DEC); 19 | 20 | Serial.print(" = "); 21 | Serial.print(dt.unixtime()); 22 | Serial.print("s / "); 23 | Serial.print(dt.unixtime() / 86400L); 24 | Serial.print("d since 1970"); 25 | 26 | Serial.println(); 27 | } 28 | 29 | void showTimeSpan(const char* txt, const TimeSpan& ts) { 30 | Serial.print(txt); 31 | Serial.print(" "); 32 | Serial.print(ts.days(), DEC); 33 | Serial.print(" days "); 34 | Serial.print(ts.hours(), DEC); 35 | Serial.print(" hours "); 36 | Serial.print(ts.minutes(), DEC); 37 | Serial.print(" minutes "); 38 | Serial.print(ts.seconds(), DEC); 39 | Serial.print(" seconds ("); 40 | Serial.print(ts.totalseconds(), DEC); 41 | Serial.print(" total seconds)"); 42 | Serial.println(); 43 | } 44 | 45 | void setup () { 46 | Serial.begin(57600); 47 | 48 | #ifndef ESP8266 49 | while (!Serial); // wait for serial port to connect. Needed for native USB 50 | #endif 51 | 52 | DateTime dt0 (0, 1, 1, 0, 0, 0); 53 | showDate("dt0", dt0); 54 | 55 | DateTime dt1 (1, 1, 1, 0, 0, 0); 56 | showDate("dt1", dt1); 57 | 58 | DateTime dt2 (2009, 1, 1, 0, 0, 0); 59 | showDate("dt2", dt2); 60 | 61 | DateTime dt3 (2009, 1, 2, 0, 0, 0); 62 | showDate("dt3", dt3); 63 | 64 | DateTime dt4 (2009, 1, 27, 0, 0, 0); 65 | showDate("dt4", dt4); 66 | 67 | DateTime dt5 (2009, 2, 27, 0, 0, 0); 68 | showDate("dt5", dt5); 69 | 70 | DateTime dt6 (2009, 12, 27, 0, 0, 0); 71 | showDate("dt6", dt6); 72 | 73 | DateTime dt7 (dt6.unixtime() + 3600); // One hour later. 74 | showDate("dt7", dt7); 75 | 76 | DateTime dt75 = dt6 + TimeSpan(0, 1, 0, 0); // One hour later with TimeSpan addition. 77 | showDate("dt7.5", dt75); 78 | 79 | DateTime dt8 (dt6.unixtime() + 86400L); // One day later. 80 | showDate("dt8", dt8); 81 | 82 | DateTime dt85 = dt6 + TimeSpan(1, 0, 0, 0); // One day later with TimeSpan addition. 83 | showDate("dt8.5", dt85); 84 | 85 | DateTime dt9 (dt6.unixtime() + 7 * 86400L); // One week later. 86 | showDate("dt9", dt9); 87 | 88 | DateTime dt95 = dt6 + TimeSpan(7, 0, 0, 0); // One week later with TimeSpan addition. 89 | showDate("dt9.5", dt95); 90 | 91 | DateTime dt10 = dt6 + TimeSpan(0, 0, 42, 42); // Fourty two minutes and fourty two seconds later. 92 | showDate("dt10", dt10); 93 | 94 | DateTime dt11 = dt6 - TimeSpan(7, 0, 0, 0); // One week ago. 95 | showDate("dt11", dt11); 96 | 97 | TimeSpan ts1 = dt6 - dt5; 98 | showTimeSpan("dt6-dt5", ts1); 99 | 100 | TimeSpan ts2 = dt10 - dt6; 101 | showTimeSpan("dt10-dt6", ts2); 102 | } 103 | 104 | void loop () { 105 | } 106 | -------------------------------------------------------------------------------- /lib/RTClib-master/examples/ds1307/ds1307.ino: -------------------------------------------------------------------------------- 1 | // Date and time functions using a DS1307 RTC connected via I2C and Wire lib 2 | #include "RTClib.h" 3 | 4 | RTC_DS1307 rtc; 5 | 6 | char daysOfTheWeek[7][12] = {"Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"}; 7 | 8 | void setup () { 9 | Serial.begin(57600); 10 | 11 | #ifndef ESP8266 12 | while (!Serial); // wait for serial port to connect. Needed for native USB 13 | #endif 14 | 15 | if (! rtc.begin()) { 16 | Serial.println("Couldn't find RTC"); 17 | Serial.flush(); 18 | abort(); 19 | } 20 | 21 | if (! rtc.isrunning()) { 22 | Serial.println("RTC is NOT running, let's set the time!"); 23 | // When time needs to be set on a new device, or after a power loss, the 24 | // following line sets the RTC to the date & time this sketch was compiled 25 | rtc.adjust(DateTime(F(__DATE__), F(__TIME__))); 26 | // This line sets the RTC with an explicit date & time, for example to set 27 | // January 21, 2014 at 3am you would call: 28 | // rtc.adjust(DateTime(2014, 1, 21, 3, 0, 0)); 29 | } 30 | 31 | // When time needs to be re-set on a previously configured device, the 32 | // following line sets the RTC to the date & time this sketch was compiled 33 | // rtc.adjust(DateTime(F(__DATE__), F(__TIME__))); 34 | // This line sets the RTC with an explicit date & time, for example to set 35 | // January 21, 2014 at 3am you would call: 36 | // rtc.adjust(DateTime(2014, 1, 21, 3, 0, 0)); 37 | } 38 | 39 | void loop () { 40 | DateTime now = rtc.now(); 41 | 42 | Serial.print(now.year(), DEC); 43 | Serial.print('/'); 44 | Serial.print(now.month(), DEC); 45 | Serial.print('/'); 46 | Serial.print(now.day(), DEC); 47 | Serial.print(" ("); 48 | Serial.print(daysOfTheWeek[now.dayOfTheWeek()]); 49 | Serial.print(") "); 50 | Serial.print(now.hour(), DEC); 51 | Serial.print(':'); 52 | Serial.print(now.minute(), DEC); 53 | Serial.print(':'); 54 | Serial.print(now.second(), DEC); 55 | Serial.println(); 56 | 57 | Serial.print(" since midnight 1/1/1970 = "); 58 | Serial.print(now.unixtime()); 59 | Serial.print("s = "); 60 | Serial.print(now.unixtime() / 86400L); 61 | Serial.println("d"); 62 | 63 | // calculate a date which is 7 days, 12 hours, 30 minutes, and 6 seconds into the future 64 | DateTime future (now + TimeSpan(7,12,30,6)); 65 | 66 | Serial.print(" now + 7d + 12h + 30m + 6s: "); 67 | Serial.print(future.year(), DEC); 68 | Serial.print('/'); 69 | Serial.print(future.month(), DEC); 70 | Serial.print('/'); 71 | Serial.print(future.day(), DEC); 72 | Serial.print(' '); 73 | Serial.print(future.hour(), DEC); 74 | Serial.print(':'); 75 | Serial.print(future.minute(), DEC); 76 | Serial.print(':'); 77 | Serial.print(future.second(), DEC); 78 | Serial.println(); 79 | 80 | Serial.println(); 81 | delay(3000); 82 | } 83 | -------------------------------------------------------------------------------- /lib/RTClib-master/examples/ds1307SqwPin/ds1307SqwPin.ino: -------------------------------------------------------------------------------- 1 | // SQW/OUT pin mode using a DS1307 RTC connected via I2C. 2 | // 3 | // According to the data sheet (http://datasheets.maxim-ic.com/en/ds/DS1307.pdf), the 4 | // DS1307's SQW/OUT pin can be set to low, high, 1Hz, 4.096kHz, 8.192kHz, or 32.768kHz. 5 | // 6 | // This sketch reads the state of the pin, then iterates through the possible values at 7 | // 5 second intervals. 8 | // 9 | 10 | // NOTE: 11 | // You must connect a pull up resistor (~10kohm) from the SQW pin up to VCC. Without 12 | // this pull up the wave output will not work! 13 | 14 | #include "RTClib.h" 15 | 16 | RTC_DS1307 rtc; 17 | 18 | int mode_index = 0; 19 | 20 | Ds1307SqwPinMode modes[] = { DS1307_OFF, DS1307_ON, DS1307_SquareWave1HZ, DS1307_SquareWave4kHz, DS1307_SquareWave8kHz, DS1307_SquareWave32kHz}; 21 | 22 | 23 | void print_mode() { 24 | Ds1307SqwPinMode mode = rtc.readSqwPinMode(); 25 | 26 | Serial.print("Sqw Pin Mode: "); 27 | switch(mode) { 28 | case DS1307_OFF: Serial.println("OFF"); break; 29 | case DS1307_ON: Serial.println("ON"); break; 30 | case DS1307_SquareWave1HZ: Serial.println("1Hz"); break; 31 | case DS1307_SquareWave4kHz: Serial.println("4.096kHz"); break; 32 | case DS1307_SquareWave8kHz: Serial.println("8.192kHz"); break; 33 | case DS1307_SquareWave32kHz: Serial.println("32.768kHz"); break; 34 | default: Serial.println("UNKNOWN"); break; 35 | } 36 | } 37 | 38 | void setup () { 39 | Serial.begin(57600); 40 | 41 | #ifndef ESP8266 42 | while (!Serial); // wait for serial port to connect. Needed for native USB 43 | #endif 44 | 45 | if (! rtc.begin()) { 46 | Serial.println("Couldn't find RTC"); 47 | Serial.flush(); 48 | abort(); 49 | } 50 | 51 | print_mode(); 52 | } 53 | 54 | void loop () { 55 | rtc.writeSqwPinMode(modes[mode_index++]); 56 | print_mode(); 57 | 58 | if (mode_index > 5) { 59 | mode_index = 0; 60 | } 61 | 62 | delay(5000); 63 | } 64 | -------------------------------------------------------------------------------- /lib/RTClib-master/examples/ds1307nvram/ds1307nvram.ino: -------------------------------------------------------------------------------- 1 | // Example of using the non-volatile RAM storage on the DS1307. 2 | // You can write up to 56 bytes from address 0 to 55. 3 | // Data will be persisted as long as the DS1307 has battery power. 4 | 5 | #include "RTClib.h" 6 | 7 | RTC_DS1307 rtc; 8 | 9 | void printnvram(uint8_t address) { 10 | Serial.print("Address 0x"); 11 | Serial.print(address, HEX); 12 | Serial.print(" = 0x"); 13 | Serial.println(rtc.readnvram(address), HEX); 14 | } 15 | 16 | void setup () { 17 | Serial.begin(57600); 18 | 19 | #ifndef ESP8266 20 | while (!Serial); // wait for serial port to connect. Needed for native USB 21 | #endif 22 | 23 | if (! rtc.begin()) { 24 | Serial.println("Couldn't find RTC"); 25 | Serial.flush(); 26 | abort(); 27 | } 28 | 29 | // Print old RAM contents on startup. 30 | Serial.println("Current NVRAM values:"); 31 | for (int i = 0; i < 6; ++i) { 32 | printnvram(i); 33 | } 34 | 35 | // Write some bytes to non-volatile RAM storage. 36 | // NOTE: You can only read and write from addresses 0 to 55 (i.e. 56 byte values). 37 | Serial.println("Writing NVRAM values."); 38 | // Example writing one byte at a time: 39 | rtc.writenvram(0, 0xFE); 40 | rtc.writenvram(1, 0xED); 41 | // Example writing multiple bytes: 42 | uint8_t writeData[4] = { 0xBE, 0xEF, 0x01, 0x02 }; 43 | rtc.writenvram(2, writeData, 4); 44 | 45 | // Read bytes from non-volatile RAM storage. 46 | Serial.println("Reading NVRAM values:"); 47 | // Example reading one byte at a time. 48 | Serial.println(rtc.readnvram(0), HEX); 49 | Serial.println(rtc.readnvram(1), HEX); 50 | // Example reading multiple bytes: 51 | uint8_t readData[4] = {0}; 52 | rtc.readnvram(readData, 4, 2); 53 | Serial.println(readData[0], HEX); 54 | Serial.println(readData[1], HEX); 55 | Serial.println(readData[2], HEX); 56 | Serial.println(readData[3], HEX); 57 | 58 | } 59 | 60 | void loop () { 61 | // Do nothing in the loop. 62 | } 63 | -------------------------------------------------------------------------------- /lib/RTClib-master/examples/ds3231/ds3231.ino: -------------------------------------------------------------------------------- 1 | // Date and time functions using a DS3231 RTC connected via I2C and Wire lib 2 | #include "RTClib.h" 3 | 4 | RTC_DS3231 rtc; 5 | 6 | char daysOfTheWeek[7][12] = {"Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"}; 7 | 8 | void setup () { 9 | Serial.begin(57600); 10 | 11 | #ifndef ESP8266 12 | while (!Serial); // wait for serial port to connect. Needed for native USB 13 | #endif 14 | 15 | if (! rtc.begin()) { 16 | Serial.println("Couldn't find RTC"); 17 | Serial.flush(); 18 | abort(); 19 | } 20 | 21 | if (rtc.lostPower()) { 22 | Serial.println("RTC lost power, let's set the time!"); 23 | // When time needs to be set on a new device, or after a power loss, the 24 | // following line sets the RTC to the date & time this sketch was compiled 25 | rtc.adjust(DateTime(F(__DATE__), F(__TIME__))); 26 | // This line sets the RTC with an explicit date & time, for example to set 27 | // January 21, 2014 at 3am you would call: 28 | // rtc.adjust(DateTime(2014, 1, 21, 3, 0, 0)); 29 | } 30 | 31 | // When time needs to be re-set on a previously configured device, the 32 | // following line sets the RTC to the date & time this sketch was compiled 33 | // rtc.adjust(DateTime(F(__DATE__), F(__TIME__))); 34 | // This line sets the RTC with an explicit date & time, for example to set 35 | // January 21, 2014 at 3am you would call: 36 | // rtc.adjust(DateTime(2014, 1, 21, 3, 0, 0)); 37 | } 38 | 39 | void loop () { 40 | DateTime now = rtc.now(); 41 | 42 | Serial.print(now.year(), DEC); 43 | Serial.print('/'); 44 | Serial.print(now.month(), DEC); 45 | Serial.print('/'); 46 | Serial.print(now.day(), DEC); 47 | Serial.print(" ("); 48 | Serial.print(daysOfTheWeek[now.dayOfTheWeek()]); 49 | Serial.print(") "); 50 | Serial.print(now.hour(), DEC); 51 | Serial.print(':'); 52 | Serial.print(now.minute(), DEC); 53 | Serial.print(':'); 54 | Serial.print(now.second(), DEC); 55 | Serial.println(); 56 | 57 | Serial.print(" since midnight 1/1/1970 = "); 58 | Serial.print(now.unixtime()); 59 | Serial.print("s = "); 60 | Serial.print(now.unixtime() / 86400L); 61 | Serial.println("d"); 62 | 63 | // calculate a date which is 7 days, 12 hours, 30 minutes, 6 seconds into the future 64 | DateTime future (now + TimeSpan(7,12,30,6)); 65 | 66 | Serial.print(" now + 7d + 12h + 30m + 6s: "); 67 | Serial.print(future.year(), DEC); 68 | Serial.print('/'); 69 | Serial.print(future.month(), DEC); 70 | Serial.print('/'); 71 | Serial.print(future.day(), DEC); 72 | Serial.print(' '); 73 | Serial.print(future.hour(), DEC); 74 | Serial.print(':'); 75 | Serial.print(future.minute(), DEC); 76 | Serial.print(':'); 77 | Serial.print(future.second(), DEC); 78 | Serial.println(); 79 | 80 | Serial.print("Temperature: "); 81 | Serial.print(rtc.getTemperature()); 82 | Serial.println(" C"); 83 | 84 | Serial.println(); 85 | delay(3000); 86 | } 87 | -------------------------------------------------------------------------------- /lib/RTClib-master/examples/interrupts1Hz/.leonardo.test.only: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/art-mx/ocpp-embedded-client/67ae0d9248a578dda3e76f46f5f40894a57058fb/lib/RTClib-master/examples/interrupts1Hz/.leonardo.test.only -------------------------------------------------------------------------------- /lib/RTClib-master/examples/interrupts1Hz/.mega2560.test.only: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/art-mx/ocpp-embedded-client/67ae0d9248a578dda3e76f46f5f40894a57058fb/lib/RTClib-master/examples/interrupts1Hz/.mega2560.test.only -------------------------------------------------------------------------------- /lib/RTClib-master/examples/interrupts1Hz/.uno.test.only: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/art-mx/ocpp-embedded-client/67ae0d9248a578dda3e76f46f5f40894a57058fb/lib/RTClib-master/examples/interrupts1Hz/.uno.test.only -------------------------------------------------------------------------------- /lib/RTClib-master/examples/interrupts1Hz/interrupts1Hz.ino: -------------------------------------------------------------------------------- 1 | /*********************************************************************** 2 | 3 | Combining RTClib with the avr-libc timing functions 4 | =================================================== 5 | 6 | The standard way of getting the current time and date with RTClib is to 7 | call the now() method of the appropriate RTC class. This, however, is 8 | somewhat slow, as it involves communicating with the RTC through the I2C 9 | bus. An alternative, more lightweight method involves configuring the 10 | RTC to deliver one pulse per second to an interrupt pin, and counting 11 | the seconds in the interrupt handler. The timekeeping is then entirely 12 | handled in the Arduino, with no I2C communication with the RTC other 13 | than during the initialization phase. 14 | 15 | On AVR-based Arduinos (Uno, Nano, Micro, ...), the Arduino core library 16 | is built on top of avr-libc, which is an implementation of the standard 17 | C library for the AVR platform. This library provides the standard C 18 | functions for handling time:[1] time(), gmtime(), mktime(), etc. The 19 | time() function is normally used to retrieve the current time from the 20 | operating system, but since we have no operating system, the avr-libc 21 | provides its own non-standard functions for implementing a time source: 22 | 23 | - set_system_time() initializes the library's idea of the current time 24 | - system_tick() steps the system time by one second. 25 | 26 | This sketch demonstrates how to combine RTClib and avr-libc in order to 27 | handle the timekeeping entirely on the Arduino from an interrupt 28 | delivered by the RTC: 29 | 30 | - RTClib is used to configure the RTC and retrieve the initial time 31 | - avr-libc is used for regular timekeeping 32 | 33 | This sketch only works on AVR-based Arduinos, as it relies on 34 | non-standard functions provided by avr-libc. 35 | 36 | [1] https://www.nongnu.org/avr-libc/user-manual/group__avr__time.html 37 | 38 | ***********************************************************************/ 39 | 40 | #include 41 | #include // standard C timing functions 42 | 43 | // Pin receiving the one-pulse-per-second signal from the RTC. 44 | // This should be an interrupt-capable pin. 45 | const uint8_t pin1pps = 2; 46 | 47 | // We will use the PCF8523 RTC, which has the handy "Second Timer". 48 | // Other RTCs could be used with their "square wave" output configured 49 | // to 1 Hz. 50 | RTC_PCF8523 rtc; 51 | 52 | void setup() { 53 | 54 | // Initialize the serial port. 55 | Serial.begin(57600); 56 | while (!Serial); // wait for serial port to connect. Needed for native USB 57 | 58 | // Initialize the RTC. 59 | if (! rtc.begin()) { 60 | Serial.println("Couldn't find RTC"); 61 | Serial.flush(); 62 | abort(); 63 | } 64 | if (!rtc.initialized() || rtc.lostPower()) { 65 | rtc.adjust(DateTime(F(__DATE__), F(__TIME__))); 66 | } 67 | rtc.deconfigureAllTimers(); // undo previous configuration, if any 68 | 69 | // Initialize the system time from the RTC time. Both avr-libc and 70 | // DateTime::secondstime() use the start of year 2000 as their 71 | // reference "epoch". 72 | set_system_time(rtc.now().secondstime()); 73 | 74 | // Keep the time in sync using the one-pulse-per-second output of the 75 | // RTC as an interrupt source and calling system_tick() from the 76 | // interrupt service routine. 77 | pinMode(pin1pps, INPUT_PULLUP); 78 | rtc.enableSecondTimer(); 79 | attachInterrupt(digitalPinToInterrupt(pin1pps), system_tick, FALLING); 80 | } 81 | 82 | void loop() { 83 | 84 | // From here on, we only use the standard C timing functions. 85 | // time() returns the current time as a single number of type time_t, 86 | // this is the number of seconds elapsed since a reference "epoch". 87 | time_t now = time(nullptr); 88 | 89 | // gmtime() converts the time to a broken-down form (year, month...) 90 | // similar to the DateTime class. Unlike localtime(), it doesn't 91 | // attempt timezone conversions. 92 | struct tm *broken_down_time = gmtime(&now); 93 | 94 | // asctime() returns a textual representation of the date and time as 95 | // a C string (pointer to a character array). The format is similar to 96 | // the DateTime::toString() format "DDD MMM DD hh:mm:ss YYYY". 97 | Serial.println(asctime(broken_down_time)); 98 | 99 | delay(1000); 100 | } 101 | -------------------------------------------------------------------------------- /lib/RTClib-master/examples/pcf8523/pcf8523.ino: -------------------------------------------------------------------------------- 1 | // Date and time functions using a PCF8523 RTC connected via I2C and Wire lib 2 | #include "RTClib.h" 3 | 4 | RTC_PCF8523 rtc; 5 | 6 | char daysOfTheWeek[7][12] = {"Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"}; 7 | 8 | void setup () { 9 | Serial.begin(57600); 10 | 11 | #ifndef ESP8266 12 | while (!Serial); // wait for serial port to connect. Needed for native USB 13 | #endif 14 | 15 | if (! rtc.begin()) { 16 | Serial.println("Couldn't find RTC"); 17 | Serial.flush(); 18 | abort(); 19 | } 20 | 21 | if (! rtc.initialized() || rtc.lostPower()) { 22 | Serial.println("RTC is NOT initialized, let's set the time!"); 23 | // When time needs to be set on a new device, or after a power loss, the 24 | // following line sets the RTC to the date & time this sketch was compiled 25 | rtc.adjust(DateTime(F(__DATE__), F(__TIME__))); 26 | // This line sets the RTC with an explicit date & time, for example to set 27 | // January 21, 2014 at 3am you would call: 28 | // rtc.adjust(DateTime(2014, 1, 21, 3, 0, 0)); 29 | // 30 | // Note: allow 2 seconds after inserting battery or applying external power 31 | // without battery before calling adjust(). This gives the PCF8523's 32 | // crystal oscillator time to stabilize. If you call adjust() very quickly 33 | // after the RTC is powered, lostPower() may still return true. 34 | } 35 | 36 | // When time needs to be re-set on a previously configured device, the 37 | // following line sets the RTC to the date & time this sketch was compiled 38 | // rtc.adjust(DateTime(F(__DATE__), F(__TIME__))); 39 | // This line sets the RTC with an explicit date & time, for example to set 40 | // January 21, 2014 at 3am you would call: 41 | // rtc.adjust(DateTime(2014, 1, 21, 3, 0, 0)); 42 | 43 | // When the RTC was stopped and stays connected to the battery, it has 44 | // to be restarted by clearing the STOP bit. Let's do this to ensure 45 | // the RTC is running. 46 | rtc.start(); 47 | 48 | // The PCF8523 can be calibrated for: 49 | // - Aging adjustment 50 | // - Temperature compensation 51 | // - Accuracy tuning 52 | // The offset mode to use, once every two hours or once every minute. 53 | // The offset Offset value from -64 to +63. See the Application Note for calculation of offset values. 54 | // https://www.nxp.com/docs/en/application-note/AN11247.pdf 55 | // The deviation in parts per million can be calculated over a period of observation. Both the drift (which can be negative) 56 | // and the observation period must be in seconds. For accuracy the variation should be observed over about 1 week. 57 | // Note: any previous calibration should cancelled prior to any new observation period. 58 | // Example - RTC gaining 43 seconds in 1 week 59 | float drift = 43; // seconds plus or minus over oservation period - set to 0 to cancel previous calibration. 60 | float period_sec = (7 * 86400); // total obsevation period in seconds (86400 = seconds in 1 day: 7 days = (7 * 86400) seconds ) 61 | float deviation_ppm = (drift / period_sec * 1000000); // deviation in parts per million (μs) 62 | float drift_unit = 4.34; // use with offset mode PCF8523_TwoHours 63 | // float drift_unit = 4.069; //For corrections every min the drift_unit is 4.069 ppm (use with offset mode PCF8523_OneMinute) 64 | int offset = round(deviation_ppm / drift_unit); 65 | // rtc.calibrate(PCF8523_TwoHours, offset); // Un-comment to perform calibration once drift (seconds) and observation period (seconds) are correct 66 | // rtc.calibrate(PCF8523_TwoHours, 0); // Un-comment to cancel previous calibration 67 | 68 | Serial.print("Offset is "); Serial.println(offset); // Print to control offset 69 | 70 | } 71 | 72 | void loop () { 73 | DateTime now = rtc.now(); 74 | 75 | Serial.print(now.year(), DEC); 76 | Serial.print('/'); 77 | Serial.print(now.month(), DEC); 78 | Serial.print('/'); 79 | Serial.print(now.day(), DEC); 80 | Serial.print(" ("); 81 | Serial.print(daysOfTheWeek[now.dayOfTheWeek()]); 82 | Serial.print(") "); 83 | Serial.print(now.hour(), DEC); 84 | Serial.print(':'); 85 | Serial.print(now.minute(), DEC); 86 | Serial.print(':'); 87 | Serial.print(now.second(), DEC); 88 | Serial.println(); 89 | 90 | Serial.print(" since midnight 1/1/1970 = "); 91 | Serial.print(now.unixtime()); 92 | Serial.print("s = "); 93 | Serial.print(now.unixtime() / 86400L); 94 | Serial.println("d"); 95 | 96 | // calculate a date which is 7 days, 12 hours and 30 seconds into the future 97 | DateTime future (now + TimeSpan(7,12,30,6)); 98 | 99 | Serial.print(" now + 7d + 12h + 30m + 6s: "); 100 | Serial.print(future.year(), DEC); 101 | Serial.print('/'); 102 | Serial.print(future.month(), DEC); 103 | Serial.print('/'); 104 | Serial.print(future.day(), DEC); 105 | Serial.print(' '); 106 | Serial.print(future.hour(), DEC); 107 | Serial.print(':'); 108 | Serial.print(future.minute(), DEC); 109 | Serial.print(':'); 110 | Serial.print(future.second(), DEC); 111 | Serial.println(); 112 | 113 | Serial.println(); 114 | delay(3000); 115 | } 116 | -------------------------------------------------------------------------------- /lib/RTClib-master/examples/pcf8523Countdown/pcf8523Countdown.ino: -------------------------------------------------------------------------------- 1 | /**************************************************************************/ 2 | /* 3 | Countdown Timer using a PCF8523 RTC connected via I2C and Wire lib 4 | with the INT/SQW pin wired to an interrupt-capable input. 5 | 6 | According to the data sheet, the PCF8523 can run countdown timers 7 | from 244 microseconds to 10.625 days: 8 | https://www.nxp.com/docs/en/data-sheet/PCF8523.pdf#page=34 9 | 10 | This sketch sets a countdown timer, and executes code when it reaches 0, 11 | then blinks the built-in LED like BlinkWithoutDelay, but without millis()! 12 | 13 | NOTE: 14 | You must connect the PCF8523's interrupt pin to your Arduino or other 15 | microcontroller on an input pin that can handle interrupts, and that has a 16 | pullup resistor. The pin will be briefly pulled low each time the countdown 17 | reaches 0. This example will not work without the interrupt pin connected! 18 | 19 | On Adafruit breakout boards, the interrupt pin is labeled 'INT' or 'SQW'. 20 | */ 21 | /**************************************************************************/ 22 | 23 | #include "RTClib.h" 24 | 25 | RTC_PCF8523 rtc; 26 | 27 | // Input pin with interrupt capability 28 | // const int timerInterruptPin = 2; // Most Arduinos 29 | const int timerInterruptPin = 5; // Adafruit Feather M0/M4/nRF52840 30 | 31 | // Variables modified during an interrupt must be declared volatile 32 | volatile bool countdownInterruptTriggered = false; 33 | volatile int numCountdownInterrupts = 0; 34 | 35 | void setup () { 36 | Serial.begin(57600); 37 | 38 | #ifndef ESP8266 39 | while (!Serial); // wait for serial port to connect. Needed for native USB 40 | #endif 41 | 42 | if (! rtc.begin()) { 43 | Serial.println("Couldn't find RTC"); 44 | Serial.flush(); 45 | abort(); 46 | } 47 | 48 | pinMode(LED_BUILTIN, OUTPUT); 49 | 50 | // Set the pin attached to PCF8523 INT to be an input with pullup to HIGH. 51 | // The PCF8523 interrupt pin will briefly pull it LOW at the end of a given 52 | // countdown period, then it will be released to be pulled HIGH again. 53 | pinMode(timerInterruptPin, INPUT_PULLUP); 54 | 55 | Serial.println(F("\nStarting PCF8523 Countdown Timer example.")); 56 | Serial.print(F("Configured to expect PCF8523 INT/SQW pin connected to input pin: ")); 57 | Serial.println(timerInterruptPin); 58 | Serial.println(F("This example will not work without the interrupt pin connected!\n\n")); 59 | 60 | // Timer configuration is not cleared on an RTC reset due to battery backup! 61 | rtc.deconfigureAllTimers(); 62 | 63 | Serial.println(F("First, use the PCF8523's 'Countdown Timer' with an interrupt.")); 64 | Serial.println(F("Set the countdown for 10 seconds and we'll let it run for 2 rounds.")); 65 | Serial.println(F("Starting Countdown Timer now...")); 66 | 67 | // These are the PCF8523's built-in "Timer Source Clock Frequencies". 68 | // They are predefined time periods you choose as your base unit of time, 69 | // depending on the length of countdown timer you need. 70 | // The minimum length of your countdown is 1 time period. 71 | // The maximum length of your countdown is 255 time periods. 72 | // 73 | // PCF8523_FrequencyHour = 1 hour, max 10.625 days (255 hours) 74 | // PCF8523_FrequencyMinute = 1 minute, max 4.25 hours 75 | // PCF8523_FrequencySecond = 1 second, max 4.25 minutes 76 | // PCF8523_Frequency64Hz = 1/64 of a second (15.625 milliseconds), max 3.984 seconds 77 | // PCF8523_Frequency4kHz = 1/4096 of a second (244 microseconds), max 62.256 milliseconds 78 | // 79 | // 80 | // These are the PCF8523's optional 'Low Pulse Widths' of time the interrupt 81 | // pin is held LOW at the end of every countdown (frequency 64Hz or longer). 82 | // 83 | // PCF8523_LowPulse3x64Hz = 46.875 ms 3/64ths second (default) 84 | // PCF8523_LowPulse4x64Hz = 62.500 ms 4/64ths second 85 | // PCF8523_LowPulse5x64Hz = 78.125 ms 5/64ths second 86 | // PCF8523_LowPulse6x64Hz = 93.750 ms 6/64ths second 87 | // PCF8523_LowPulse8x64Hz = 125.000 ms 8/64ths second 88 | // PCF8523_LowPulse10x64Hz = 156.250 ms 10/64ths second 89 | // PCF8523_LowPulse12x64Hz = 187.500 ms 12/64ths second 90 | // PCF8523_LowPulse14x64Hz = 218.750 ms 14/64ths second 91 | // 92 | // 93 | // Uncomment an example below: 94 | 95 | // rtc.enableCountdownTimer(PCF8523_FrequencyHour, 24); // 1 day 96 | // rtc.enableCountdownTimer(PCF8523_FrequencyMinute, 150); // 2.5 hours 97 | rtc.enableCountdownTimer(PCF8523_FrequencySecond, 10); // 10 seconds 98 | // rtc.enableCountdownTimer(PCF8523_Frequency64Hz, 32); // 1/2 second 99 | // rtc.enableCountdownTimer(PCF8523_Frequency64Hz, 16); // 1/4 second 100 | // rtc.enableCountdownTimer(PCF8523_Frequency4kHz, 205); // 50 milliseconds 101 | 102 | attachInterrupt(digitalPinToInterrupt(timerInterruptPin), countdownOver, FALLING); 103 | 104 | // This message proves we're not blocked while counting down! 105 | Serial.println(F(" While we're waiting, a word of caution:")); 106 | Serial.println(F(" When starting a new countdown timer, the first time period is not of fixed")); 107 | Serial.println(F(" duration. The amount of inaccuracy for the first time period is up to one full")); 108 | Serial.println(F(" clock frequency. Example: just the first second of the first round of a new")); 109 | Serial.println(F(" countdown based on PCF8523_FrequencySecond may be off by as much as 1 second!")); 110 | Serial.println(F(" For critical timing, consider starting actions on the first interrupt.")); 111 | } 112 | 113 | // Triggered by the PCF8523 Countdown Timer interrupt at the end of a countdown 114 | // period. Meanwhile, the PCF8523 immediately starts the countdown again. 115 | void countdownOver () { 116 | // Set a flag to run code in the loop(): 117 | countdownInterruptTriggered = true; 118 | numCountdownInterrupts++; 119 | } 120 | 121 | // Triggered by the PCF8523 Second Timer every second. 122 | void toggleLed () { 123 | // Run certain types of fast executing code here: 124 | digitalWrite(LED_BUILTIN, !digitalRead(LED_BUILTIN)); 125 | } 126 | 127 | void loop () { 128 | if (countdownInterruptTriggered && numCountdownInterrupts == 1) { 129 | Serial.println(F("1st countdown interrupt triggered. Accurate timekeeping starts now.")); 130 | countdownInterruptTriggered = false; // don't come in here again 131 | } else if (countdownInterruptTriggered && numCountdownInterrupts == 2) { 132 | Serial.println(F("2nd countdown interrupt triggered. Disabling countdown and detaching interrupt.\n\n")); 133 | rtc.disableCountdownTimer(); 134 | detachInterrupt(digitalPinToInterrupt(timerInterruptPin)); 135 | delay(2000); 136 | 137 | 138 | Serial.println(F("Now, set up the PCF8523's 'Second Timer' to toggle the built-in LED at 1Hz...")); 139 | attachInterrupt(digitalPinToInterrupt(timerInterruptPin), toggleLed, FALLING); 140 | rtc.enableSecondTimer(); 141 | Serial.println(F("Look for the built-in LED to flash 1 second ON, 1 second OFF, repeat. ")); 142 | Serial.println(F("Meanwhile this program will use delay() to block code execution briefly")); 143 | Serial.println(F("before moving on to the last example. Notice the LED keeps blinking!\n\n")); 144 | delay(20000); // less accurate, blocks execution here. Meanwhile Second Timer keeps running. 145 | rtc.disableSecondTimer(); 146 | detachInterrupt(digitalPinToInterrupt(timerInterruptPin)); 147 | 148 | 149 | Serial.println(F("Lastly, set up a Countdown Timer that works without attaching an interrupt...")); 150 | rtc.enableCountdownTimer(PCF8523_Frequency64Hz, 32, PCF8523_LowPulse8x64Hz); 151 | Serial.println(F("Look for the LED to turn on every 1/2 second and stay lit for 1/8th of a second.")); 152 | Serial.println(F("The countdown was set to a source clock frequency of 64 Hz (1/64th of a second)")); 153 | Serial.println(F("for a length of 32 time periods. 32 * 1/64th of a second is 1/2 of a second.")); 154 | Serial.println(F("The low pulse duration was set to 125 ms, or 1/8th of a second.")); 155 | Serial.println(F("The loop() keeps the built-in LED set to the opposite state of the INT/SQW pin.")); 156 | 157 | 158 | countdownInterruptTriggered = false; // don't come in here again 159 | } 160 | 161 | // While countdown running, INT/SQW pullup to HIGH, set LED to LOW (off) 162 | // When countdown is over, INT/SQW pulled down LOW, set LED to HIGH (on) 163 | digitalWrite(LED_BUILTIN, !digitalRead(timerInterruptPin)); 164 | } 165 | -------------------------------------------------------------------------------- /lib/RTClib-master/examples/pcf8563/pcf8563.ino: -------------------------------------------------------------------------------- 1 | // Date and time functions using a PCF8563 RTC connected via I2C and Wire lib 2 | #include "RTClib.h" 3 | 4 | RTC_PCF8563 rtc; 5 | 6 | char daysOfTheWeek[7][12] = {"Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"}; 7 | 8 | void setup () { 9 | Serial.begin(115200); 10 | 11 | #ifndef ESP8266 12 | while (!Serial); // wait for serial port to connect. Needed for native USB 13 | #endif 14 | 15 | if (! rtc.begin()) { 16 | Serial.println("Couldn't find RTC"); 17 | Serial.flush(); 18 | abort(); 19 | } 20 | 21 | if (rtc.lostPower()) { 22 | Serial.println("RTC is NOT initialized, let's set the time!"); 23 | // When time needs to be set on a new device, or after a power loss, the 24 | // following line sets the RTC to the date & time this sketch was compiled 25 | rtc.adjust(DateTime(F(__DATE__), F(__TIME__))); 26 | // This line sets the RTC with an explicit date & time, for example to set 27 | // January 21, 2014 at 3am you would call: 28 | // rtc.adjust(DateTime(2014, 1, 21, 3, 0, 0)); 29 | // 30 | // Note: allow 2 seconds after inserting battery or applying external power 31 | // without battery before calling adjust(). This gives the PCF8523's 32 | // crystal oscillator time to stabilize. If you call adjust() very quickly 33 | // after the RTC is powered, lostPower() may still return true. 34 | } 35 | 36 | // When time needs to be re-set on a previously configured device, the 37 | // following line sets the RTC to the date & time this sketch was compiled 38 | // rtc.adjust(DateTime(F(__DATE__), F(__TIME__))); 39 | // This line sets the RTC with an explicit date & time, for example to set 40 | // January 21, 2014 at 3am you would call: 41 | // rtc.adjust(DateTime(2014, 1, 21, 3, 0, 0)); 42 | 43 | // When the RTC was stopped and stays connected to the battery, it has 44 | // to be restarted by clearing the STOP bit. Let's do this to ensure 45 | // the RTC is running. 46 | rtc.start(); 47 | } 48 | 49 | void loop () { 50 | DateTime now = rtc.now(); 51 | 52 | Serial.print(now.year(), DEC); 53 | Serial.print('/'); 54 | Serial.print(now.month(), DEC); 55 | Serial.print('/'); 56 | Serial.print(now.day(), DEC); 57 | Serial.print(" ("); 58 | Serial.print(daysOfTheWeek[now.dayOfTheWeek()]); 59 | Serial.print(") "); 60 | Serial.print(now.hour(), DEC); 61 | Serial.print(':'); 62 | Serial.print(now.minute(), DEC); 63 | Serial.print(':'); 64 | Serial.print(now.second(), DEC); 65 | Serial.println(); 66 | 67 | Serial.print(" since midnight 1/1/1970 = "); 68 | Serial.print(now.unixtime()); 69 | Serial.print("s = "); 70 | Serial.print(now.unixtime() / 86400L); 71 | Serial.println("d"); 72 | 73 | // calculate a date which is 7 days, 12 hours and 30 seconds into the future 74 | DateTime future (now + TimeSpan(7,12,30,6)); 75 | 76 | Serial.print(" now + 7d + 12h + 30m + 6s: "); 77 | Serial.print(future.year(), DEC); 78 | Serial.print('/'); 79 | Serial.print(future.month(), DEC); 80 | Serial.print('/'); 81 | Serial.print(future.day(), DEC); 82 | Serial.print(' '); 83 | Serial.print(future.hour(), DEC); 84 | Serial.print(':'); 85 | Serial.print(future.minute(), DEC); 86 | Serial.print(':'); 87 | Serial.print(future.second(), DEC); 88 | Serial.println(); 89 | 90 | Serial.println(); 91 | delay(3000); 92 | } 93 | -------------------------------------------------------------------------------- /lib/RTClib-master/examples/pcf8563_interrupt/pcf8563_interrupt.ino: -------------------------------------------------------------------------------- 1 | // Date and time functions using a PCF8563 RTC connected via I2C and Wire lib 2 | #include "RTClib.h" 3 | 4 | RTC_PCF8563 rtc; 5 | 6 | char daysOfTheWeek[7][12] = {"Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"}; 7 | 8 | // use D2 for INT0; attach to CLKOUT pin on RTC 9 | const uint8_t INT_PIN = 2; 10 | 11 | // flag to update serial; set in interrupt callback 12 | volatile uint8_t tick_tock = 1; 13 | 14 | // INT0 interrupt callback; update tick_tock flag 15 | void set_tick_tock(void) { 16 | tick_tock = 1; 17 | } 18 | 19 | void setup () { 20 | Serial.begin(115200); 21 | 22 | #ifndef ESP8266 23 | while (!Serial); // wait for serial port to connect. Needed for native USB 24 | #endif 25 | 26 | 27 | pinMode(INT_PIN, INPUT); // set up interrupt pin 28 | digitalWrite(INT_PIN, HIGH); // turn on pullup resistors 29 | // attach interrupt to set_tick_tock callback on rising edge of INT0 30 | attachInterrupt(digitalPinToInterrupt(INT_PIN), set_tick_tock, RISING); 31 | 32 | if (! rtc.begin()) { 33 | Serial.println("Couldn't find RTC"); 34 | Serial.flush(); 35 | abort(); 36 | } 37 | 38 | if (rtc.lostPower()) { 39 | Serial.println("RTC is NOT initialized, let's set the time!"); 40 | // When time needs to be set on a new device, or after a power loss, the 41 | // following line sets the RTC to the date & time this sketch was compiled 42 | rtc.adjust(DateTime(F(__DATE__), F(__TIME__))); 43 | // This line sets the RTC with an explicit date & time, for example to set 44 | // January 21, 2014 at 3am you would call: 45 | // rtc.adjust(DateTime(2014, 1, 21, 3, 0, 0)); 46 | // 47 | // Note: allow 2 seconds after inserting battery or applying external power 48 | // without battery before calling adjust(). This gives the PCF8523's 49 | // crystal oscillator time to stabilize. If you call adjust() very quickly 50 | // after the RTC is powered, lostPower() may still return true. 51 | } 52 | 53 | 54 | 55 | // When time needs to be re-set on a previously configured device, the 56 | // following line sets the RTC to the date & time this sketch was compiled 57 | // rtc.adjust(DateTime(F(__DATE__), F(__TIME__))); 58 | // This line sets the RTC with an explicit date & time, for example to set 59 | // January 21, 2014 at 3am you would call: 60 | // rtc.adjust(DateTime(2014, 1, 21, 3, 0, 0)); 61 | 62 | // When the RTC was stopped and stays connected to the battery, it has 63 | // to be restarted by clearing the STOP bit. Let's do this to ensure 64 | // the RTC is running. 65 | rtc.start(); 66 | 67 | // turn on 1Hz clock out, used as INT0 for serial update every second 68 | rtc.writeSqwPinMode(PCF8563_SquareWave1Hz); 69 | } 70 | 71 | void loop () { 72 | 73 | // check if time display should be output 74 | if(tick_tock) { 75 | 76 | DateTime now = rtc.now(); 77 | 78 | char time_format[] = "hh:mm:ss AP"; 79 | char date_format[] = "MM/DD/YYYY"; 80 | 81 | Serial.println(now.toString(time_format)); 82 | Serial.println(now.toString(date_format)); 83 | Serial.println(); 84 | 85 | tick_tock = 0; 86 | 87 | } 88 | 89 | } 90 | -------------------------------------------------------------------------------- /lib/RTClib-master/examples/softrtc/softrtc.ino: -------------------------------------------------------------------------------- 1 | // Date and time functions using just software, based on millis() & timer 2 | 3 | #include "RTClib.h" 4 | 5 | RTC_Millis rtc; 6 | 7 | void setup () { 8 | Serial.begin(57600); 9 | 10 | #ifndef ESP8266 11 | while (!Serial); // wait for serial port to connect. Needed for native USB 12 | #endif 13 | 14 | // following line sets the RTC to the date & time this sketch was compiled 15 | rtc.begin(DateTime(F(__DATE__), F(__TIME__))); 16 | // This line sets the RTC with an explicit date & time, for example to set 17 | // January 21, 2014 at 3am you would call: 18 | // rtc.adjust(DateTime(2014, 1, 21, 3, 0, 0)); 19 | } 20 | 21 | void loop () { 22 | DateTime now = rtc.now(); 23 | 24 | Serial.print(now.year(), DEC); 25 | Serial.print('/'); 26 | Serial.print(now.month(), DEC); 27 | Serial.print('/'); 28 | Serial.print(now.day(), DEC); 29 | Serial.print(' '); 30 | Serial.print(now.hour(), DEC); 31 | Serial.print(':'); 32 | Serial.print(now.minute(), DEC); 33 | Serial.print(':'); 34 | Serial.print(now.second(), DEC); 35 | Serial.println(); 36 | 37 | Serial.print(" seconds since 1970: "); 38 | Serial.println(now.unixtime()); 39 | 40 | // calculate a date which is 7 days and 30 seconds into the future 41 | DateTime future (now.unixtime() + 7 * 86400L + 30); 42 | 43 | Serial.print(" now + 7d + 30s: "); 44 | Serial.print(future.year(), DEC); 45 | Serial.print('/'); 46 | Serial.print(future.month(), DEC); 47 | Serial.print('/'); 48 | Serial.print(future.day(), DEC); 49 | Serial.print(' '); 50 | Serial.print(future.hour(), DEC); 51 | Serial.print(':'); 52 | Serial.print(future.minute(), DEC); 53 | Serial.print(':'); 54 | Serial.print(future.second(), DEC); 55 | Serial.println(); 56 | 57 | Serial.println(); 58 | delay(3000); 59 | } 60 | -------------------------------------------------------------------------------- /lib/RTClib-master/examples/timestamp/timestamp.ino: -------------------------------------------------------------------------------- 1 | /* Timestamp functions using a DS1307 RTC connected via I2C and Wire lib 2 | ** 3 | ** Useful for file name 4 | ** ` SD.open(time.timestamp()+".log", FILE_WRITE) ` 5 | ** 6 | ** 7 | ** Created: 2015-06-01 by AxelTB 8 | ** Last Edit: 9 | */ 10 | 11 | #include "RTClib.h" 12 | 13 | RTC_DS1307 rtc; 14 | 15 | void setup () { 16 | Serial.begin(57600); 17 | 18 | #ifndef ESP8266 19 | while (!Serial); // wait for serial port to connect. Needed for native USB 20 | #endif 21 | 22 | if (! rtc.begin()) { 23 | Serial.println("Couldn't find RTC"); 24 | Serial.flush(); 25 | abort(); 26 | } 27 | 28 | if (! rtc.isrunning()) { 29 | Serial.println("RTC is NOT running, let's set the time!"); 30 | // When time needs to be set on a new device, or after a power loss, the 31 | // following line sets the RTC to the date & time this sketch was compiled 32 | rtc.adjust(DateTime(F(__DATE__), F(__TIME__))); 33 | // This line sets the RTC with an explicit date & time, for example to set 34 | // January 21, 2014 at 3am you would call: 35 | // rtc.adjust(DateTime(2014, 1, 21, 3, 0, 0)); 36 | } 37 | 38 | // When time needs to be re-set on a previously configured device, the 39 | // following line sets the RTC to the date & time this sketch was compiled 40 | // rtc.adjust(DateTime(F(__DATE__), F(__TIME__))); 41 | // This line sets the RTC with an explicit date & time, for example to set 42 | // January 21, 2014 at 3am you would call: 43 | // rtc.adjust(DateTime(2014, 1, 21, 3, 0, 0)); 44 | } 45 | 46 | void loop() { 47 | DateTime time = rtc.now(); 48 | 49 | //Full Timestamp 50 | Serial.println(String("DateTime::TIMESTAMP_FULL:\t")+time.timestamp(DateTime::TIMESTAMP_FULL)); 51 | 52 | //Date Only 53 | Serial.println(String("DateTime::TIMESTAMP_DATE:\t")+time.timestamp(DateTime::TIMESTAMP_DATE)); 54 | 55 | //Full Timestamp 56 | Serial.println(String("DateTime::TIMESTAMP_TIME:\t")+time.timestamp(DateTime::TIMESTAMP_TIME)); 57 | 58 | Serial.println("\n"); 59 | 60 | //Delay 5s 61 | delay(5000); 62 | } 63 | -------------------------------------------------------------------------------- /lib/RTClib-master/examples/toString/toString.ino: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | RTC_DS1307 rtc; 5 | 6 | 7 | void setup () { 8 | Serial.begin(57600); 9 | 10 | #ifndef ESP8266 11 | while (!Serial); // wait for serial port to connect. Needed for native USB 12 | #endif 13 | 14 | if (! rtc.begin()) { 15 | Serial.println("Couldn't find RTC"); 16 | Serial.flush(); 17 | abort(); 18 | } 19 | 20 | if (! rtc.isrunning()) { 21 | Serial.println("RTC is NOT running, let's set the time!"); 22 | // When time needs to be set on a new device, or after a power loss, the 23 | // following line sets the RTC to the date & time this sketch was compiled 24 | rtc.adjust(DateTime(F(__DATE__), F(__TIME__))); 25 | // This line sets the RTC with an explicit date & time, for example to set 26 | // January 21, 2014 at 3am you would call: 27 | // rtc.adjust(DateTime(2014, 1, 21, 3, 0, 0)); 28 | } 29 | 30 | // When time needs to be re-set on a previously configured device, the 31 | // following line sets the RTC to the date & time this sketch was compiled 32 | // rtc.adjust(DateTime(F(__DATE__), F(__TIME__))); 33 | // This line sets the RTC with an explicit date & time, for example to set 34 | // January 21, 2014 at 3am you would call: 35 | // rtc.adjust(DateTime(2014, 1, 21, 3, 0, 0)); 36 | } 37 | 38 | void loop() { 39 | 40 | DateTime now = rtc.now(); 41 | 42 | //buffer can be defined using following combinations: 43 | //hh - the hour with a leading zero (00 to 23) 44 | //mm - the minute with a leading zero (00 to 59) 45 | //ss - the whole second with a leading zero where applicable (00 to 59) 46 | //YYYY - the year as four digit number 47 | //YY - the year as two digit number (00-99) 48 | //MM - the month as number with a leading zero (01-12) 49 | //MMM - the abbreviated English month name ('Jan' to 'Dec') 50 | //DD - the day as number with a leading zero (01 to 31) 51 | //DDD - the abbreviated English day name ('Mon' to 'Sun') 52 | 53 | char buf1[] = "hh:mm"; 54 | Serial.println(now.toString(buf1)); 55 | 56 | char buf2[] = "YYMMDD-hh:mm:ss"; 57 | Serial.println(now.toString(buf2)); 58 | 59 | char buf3[] = "Today is DDD, MMM DD YYYY"; 60 | Serial.println(now.toString(buf3)); 61 | 62 | char buf4[] = "MM-DD-YYYY"; 63 | Serial.println(now.toString(buf4)); 64 | 65 | delay(1000); 66 | } 67 | -------------------------------------------------------------------------------- /lib/RTClib-master/keywords.txt: -------------------------------------------------------------------------------- 1 | ####################################### 2 | # Syntax Coloring Map For RTClib 3 | ####################################### 4 | 5 | ####################################### 6 | # Datatypes (KEYWORD1) 7 | ####################################### 8 | 9 | DateTime KEYWORD1 10 | TimeSpan KEYWORD1 11 | RTC_DS1307 KEYWORD1 12 | RTC_DS3231 KEYWORD1 13 | RTC_PCF8523 KEYWORD1 14 | RTC_PCF8563 KEYWORD1 15 | RTC_Millis KEYWORD1 16 | RTC_Micros KEYWORD1 17 | Ds1307SqwPinMode KEYWORD1 18 | Ds3231SqwPinMode KEYWORD1 19 | Ds3231Alarm1Mode KEYWORD1 20 | Ds3231Alarm2Mode KEYWORD1 21 | Pcf8523SqwPinMode KEYWORD1 22 | PCF8523TimerClockFreq KEYWORD1 23 | PCF8523TimerIntPulse KEYWORD1 24 | Pcf8523OffsetMode KEYWORD1 25 | Pcf8563SqwPinMode KEYWORD1 26 | 27 | ####################################### 28 | # Methods and Functions (KEYWORD2) 29 | ####################################### 30 | 31 | isValid KEYWORD2 32 | year KEYWORD2 33 | month KEYWORD2 34 | day KEYWORD2 35 | hour KEYWORD2 36 | twelveHour KEYWORD2 37 | isPM KEYWORD2 38 | minute KEYWORD2 39 | second KEYWORD2 40 | dayOfTheWeek KEYWORD2 41 | secondstime KEYWORD2 42 | unixtime KEYWORD2 43 | days KEYWORD2 44 | hours KEYWORD2 45 | minutes KEYWORD2 46 | seconds KEYWORD2 47 | totalseconds KEYWORD2 48 | begin KEYWORD2 49 | adjust KEYWORD2 50 | adjustDrift KEYWORD2 51 | isrunning KEYWORD2 52 | now KEYWORD2 53 | readSqwPinMode KEYWORD2 54 | writeSqwPinMode KEYWORD2 55 | timestamp KEYWORD2 56 | toString KEYWORD2 57 | readnvram KEYWORD2 58 | writenvram KEYWORD2 59 | setAlarm1 KEYWORD2 60 | setAlarm2 KEYWORD2 61 | disableAlarm KEYWORD2 62 | clearAlarm KEYWORD2 63 | alarmFired KEYWORD2 64 | getTemperature KEYWORD2 65 | lostPower KEYWORD2 66 | initialized KEYWORD2 67 | enableSecondTimer KEYWORD2 68 | disableSecondTimer KEYWORD2 69 | enableCountdownTimer KEYWORD2 70 | disableCountdownTimer KEYWORD2 71 | deconfigureAllTimers KEYWORD2 72 | calibrate KEYWORD2 73 | enable32K KEYWORD2 74 | disable32K KEYWORD2 75 | isEnabled32K KEYWORD2 76 | 77 | ####################################### 78 | # Constants (LITERAL1) 79 | ####################################### 80 | TIMESTAMP_FULL LITERAL1 81 | TIMESTAMP_DATE LITERAL1 82 | TIMESTAMP_TIME LITERAL1 83 | 84 | -------------------------------------------------------------------------------- /lib/RTClib-master/library.properties: -------------------------------------------------------------------------------- 1 | name=RTClib 2 | version=1.12.5 3 | author=Adafruit 4 | maintainer=Adafruit 5 | sentence=A fork of Jeelab's fantastic RTC library 6 | paragraph=A fork of Jeelab's fantastic RTC library 7 | category=Timing 8 | url=https://github.com/adafruit/RTClib 9 | architectures=* 10 | depends=TinyWireM 11 | -------------------------------------------------------------------------------- /lib/RTClib-master/license.txt: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2019 Adafruit Industries 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /lib/TinyWireM-master/.github/ISSUE_TEMPLATE.md: -------------------------------------------------------------------------------- 1 | Thank you for opening an issue on an Adafruit Arduino library repository. To 2 | improve the speed of resolution please review the following guidelines and 3 | common troubleshooting steps below before creating the issue: 4 | 5 | - **Do not use GitHub issues for troubleshooting projects and issues.** Instead use 6 | the forums at http://forums.adafruit.com to ask questions and troubleshoot why 7 | something isn't working as expected. In many cases the problem is a common issue 8 | that you will more quickly receive help from the forum community. GitHub issues 9 | are meant for known defects in the code. If you don't know if there is a defect 10 | in the code then start with troubleshooting on the forum first. 11 | 12 | - **If following a tutorial or guide be sure you didn't miss a step.** Carefully 13 | check all of the steps and commands to run have been followed. Consult the 14 | forum if you're unsure or have questions about steps in a guide/tutorial. 15 | 16 | - **For Arduino projects check these very common issues to ensure they don't apply**: 17 | 18 | - For uploading sketches or communicating with the board make sure you're using 19 | a **USB data cable** and **not** a **USB charge-only cable**. It is sometimes 20 | very hard to tell the difference between a data and charge cable! Try using the 21 | cable with other devices or swapping to another cable to confirm it is not 22 | the problem. 23 | 24 | - **Be sure you are supplying adequate power to the board.** Check the specs of 25 | your board and plug in an external power supply. In many cases just 26 | plugging a board into your computer is not enough to power it and other 27 | peripherals. 28 | 29 | - **Double check all soldering joints and connections.** Flakey connections 30 | cause many mysterious problems. See the [guide to excellent soldering](https://learn.adafruit.com/adafruit-guide-excellent-soldering/tools) for examples of good solder joints. 31 | 32 | - **Ensure you are using an official Arduino or Adafruit board.** We can't 33 | guarantee a clone board will have the same functionality and work as expected 34 | with this code and don't support them. 35 | 36 | If you're sure this issue is a defect in the code and checked the steps above 37 | please fill in the following fields to provide enough troubleshooting information. 38 | You may delete the guideline and text above to just leave the following details: 39 | 40 | - Arduino board: **INSERT ARDUINO BOARD NAME/TYPE HERE** 41 | 42 | - Arduino IDE version (found in Arduino -> About Arduino menu): **INSERT ARDUINO 43 | VERSION HERE** 44 | 45 | - List the steps to reproduce the problem below (if possible attach a sketch or 46 | copy the sketch code in too): **LIST REPRO STEPS BELOW** 47 | -------------------------------------------------------------------------------- /lib/TinyWireM-master/.github/PULL_REQUEST_TEMPLATE.md: -------------------------------------------------------------------------------- 1 | Thank you for creating a pull request to contribute to Adafruit's GitHub code! 2 | Before you open the request please review the following guidelines and tips to 3 | help it be more easily integrated: 4 | 5 | - **Describe the scope of your change--i.e. what the change does and what parts 6 | of the code were modified.** This will help us understand any risks of integrating 7 | the code. 8 | 9 | - **Describe any known limitations with your change.** For example if the change 10 | doesn't apply to a supported platform of the library please mention it. 11 | 12 | - **Please run any tests or examples that can exercise your modified code.** We 13 | strive to not break users of the code and running tests/examples helps with this 14 | process. 15 | 16 | Thank you again for contributing! We will try to test and integrate the change 17 | as soon as we can, but be aware we have many GitHub repositories to manage and 18 | can't immediately respond to every request. There is no need to bump or check in 19 | on a pull request (it will clutter the discussion of the request). 20 | 21 | Also don't be worried if the request is closed or not integrated--sometimes the 22 | priorities of Adafruit's GitHub code (education, ease of use) might not match the 23 | priorities of the pull request. Don't fret, the open source community thrives on 24 | forks and GitHub makes it easy to keep your changes in a forked repo. 25 | 26 | After reviewing the guidelines above you can delete this text from the pull request. 27 | -------------------------------------------------------------------------------- /lib/TinyWireM-master/.github/workflows/githubci.yml: -------------------------------------------------------------------------------- 1 | name: Arduino Library CI 2 | 3 | on: [pull_request, push, repository_dispatch] 4 | 5 | jobs: 6 | build: 7 | runs-on: ubuntu-latest 8 | 9 | steps: 10 | - uses: actions/setup-python@v1 11 | with: 12 | python-version: '3.x' 13 | - uses: actions/checkout@v2 14 | - uses: actions/checkout@v2 15 | with: 16 | repository: adafruit/ci-arduino 17 | path: ci 18 | 19 | - name: pre-install 20 | run: bash ci/actions_install.sh 21 | 22 | - name: test platforms 23 | run: python3 ci/build_platform.py trinket_3v trinket_5v gemma 24 | 25 | - name: clang 26 | run: python3 ci/run-clang-format.py -e "ci/*" -e "bin/*" -r . 27 | 28 | - name: doxygen 29 | env: 30 | GH_REPO_TOKEN: ${{ secrets.GH_REPO_TOKEN }} 31 | PRETTYNAME : "Adafruit TinyWireM Library" 32 | run: bash ci/doxy_gen_and_deploy.sh 33 | -------------------------------------------------------------------------------- /lib/TinyWireM-master/README.md: -------------------------------------------------------------------------------- 1 | # TinyWireM [![Build Status](https://github.com/adafruit/TinyWireM/workflows/Arduino%20Library%20CI/badge.svg)](https://github.com/adafruit/TinyWireM/actions)[![Documentation](https://github.com/adafruit/ci-arduino/blob/master/assets/doxygen_badge.svg)](http://adafruit.github.io/TinyWireM/html/index.html) 2 | 3 | ATtiny (e.g. Adafruit Trinket, Gemma) I2C library, adapted from BroHogan's code on Arduino Playground: http://playground.arduino.cc/Code/USIi2c 4 | 5 | Minor changes for consistency with the Arduino 1.0 Wire library (e.g. uses write() instead of send()). Buffer size slightly increased for Adafruit_LEDBackpack use. 6 | 7 | On the Trinket boards, pin #0 is SDA (I2C data), pin #2 is SCK (I2C clock). 8 | -------------------------------------------------------------------------------- /lib/TinyWireM-master/TinyWireM.cpp: -------------------------------------------------------------------------------- 1 | /*! 2 | * @file TinyWireM.cpp 3 | * 4 | * @mainpage Adafruit TinyWireM Library 5 | * 6 | * @section intro_sec Introduction 7 | * 8 | * TinyWireM.cpp - a wrapper class for TWI/I2C Master library for the ATtiny on 9 | * Arduino 1/21/2011 BroHogan - brohoganx10 at gmail dot com 10 | * 11 | * **** See TinyWireM.h for Credits and Usage information **** 12 | * 13 | * @section license License 14 | * 15 | * This library is free software; you can redistribute it and/or modify it under 16 | * the terms of the GNU General Public License as published by the Free Software 17 | * Foundation; either version 2.1 of the License, or any later version. 18 | * 19 | * This program is distributed in the hope that it will be useful, but WITHOUT 20 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS 21 | * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more 22 | * details. 23 | */ 24 | 25 | extern "C" { 26 | //#include "USI_TWI_Master.h" 27 | //#include 28 | //#include 29 | //#include 30 | } 31 | 32 | #include "TinyWireM.h" 33 | #include "USI_TWI_Master.h" 34 | 35 | // Initialize Class Variables ////////////////////////////////////////////////// 36 | uint8_t USI_TWI::USI_Buf[USI_BUF_SIZE]; // holds I2C send and receive data 37 | uint8_t USI_TWI::USI_BufIdx = 0; // current number of bytes in the send buff 38 | uint8_t USI_TWI::USI_LastRead = 0; // number of bytes read so far 39 | uint8_t USI_TWI::USI_BytesAvail = 0; // number of bytes requested but not read 40 | 41 | // Constructors //////////////////////////////////////////////////////////////// 42 | 43 | USI_TWI::USI_TWI() {} 44 | 45 | // Public Methods ////////////////////////////////////////////////////////////// 46 | 47 | // int USI_TWI::peek(){} 48 | // void USI_TWI::flush(){} 49 | 50 | void USI_TWI::begin() { // initialize I2C lib 51 | USI_TWI_Master_Initialise(); 52 | } 53 | 54 | void USI_TWI::beginTransmission( 55 | uint8_t slaveAddr) { // setup address & write bit 56 | USI_BufIdx = 0; 57 | USI_Buf[USI_BufIdx] = (slaveAddr << TWI_ADR_BITS) | USI_SEND; 58 | } 59 | 60 | size_t USI_TWI::write(uint8_t data) { // buffers up data to send 61 | if (USI_BufIdx >= USI_BUF_SIZE - 1) 62 | return 0; // dont blow out the buffer 63 | USI_BufIdx++; // inc for next byte in buffer 64 | USI_Buf[USI_BufIdx] = data; 65 | return 1; 66 | } 67 | 68 | uint8_t USI_TWI::endTransmission() { return endTransmission(1); } 69 | 70 | uint8_t USI_TWI::endTransmission(uint8_t stop) { // actually sends the buffer 71 | bool xferOK = false; 72 | uint8_t errorCode = 0; 73 | xferOK = USI_TWI_Start_Read_Write( 74 | USI_Buf, USI_BufIdx + 1); // core func that does the work 75 | USI_BufIdx = 0; 76 | if (xferOK) { 77 | if (stop) { 78 | errorCode = USI_TWI_Master_Stop(); 79 | if (errorCode == 0) { 80 | errorCode = USI_TWI_Get_State_Info(); 81 | return errorCode; 82 | } 83 | } 84 | return 0; 85 | } else { // there was an error 86 | errorCode = 87 | USI_TWI_Get_State_Info(); // this function returns the error number 88 | return errorCode; 89 | } 90 | } 91 | 92 | uint8_t 93 | USI_TWI::requestFrom(uint8_t slaveAddr, 94 | uint8_t numBytes) { // setup for receiving from slave 95 | bool xferOK = false; 96 | uint8_t errorCode = 0; 97 | USI_LastRead = 0; 98 | USI_BytesAvail = numBytes; // save this off in a global 99 | numBytes++; // add extra byte to transmit header 100 | USI_Buf[0] = 101 | (slaveAddr << TWI_ADR_BITS) | USI_RCVE; // setup address & Rcve bit 102 | xferOK = USI_TWI_Start_Read_Write(USI_Buf, 103 | numBytes); // core func that does the work 104 | // USI_Buf now holds the data read 105 | if (xferOK) { 106 | errorCode = USI_TWI_Master_Stop(); 107 | if (errorCode == 0) { 108 | errorCode = USI_TWI_Get_State_Info(); 109 | return errorCode; 110 | } 111 | return 0; 112 | } else { // there was an error 113 | errorCode = 114 | USI_TWI_Get_State_Info(); // this function returns the error number 115 | return errorCode; 116 | } 117 | } 118 | 119 | int USI_TWI::read() { // returns the bytes received one at a time 120 | USI_LastRead++; // inc first since first uint8_t read is in USI_Buf[1] 121 | return USI_Buf[USI_LastRead]; 122 | } 123 | 124 | int USI_TWI::available() { // the bytes available that haven't been read yet 125 | return USI_BytesAvail - (USI_LastRead); 126 | } 127 | 128 | // Preinstantiate Objects ////////////////////////////////////////////////////// 129 | 130 | /*! 131 | * @brief Makes TinyWireM an object of USI_TWI 132 | */ 133 | USI_TWI TinyWireM = USI_TWI(); 134 | -------------------------------------------------------------------------------- /lib/TinyWireM-master/TinyWireM.h: -------------------------------------------------------------------------------- 1 | /*! 2 | * @file TinyWireM.h 3 | * 4 | * TinyWireM.h - a wrapper(+) class for TWI/I2C Master library for the ATtiny on 5 | *Arduino 1/21/2011 BroHogan - brohoganx10 at gmail dot com 6 | * 7 | * Thanks to 'jkl' for the gcc version of Atmel's USI_TWI_Master code 8 | * http://www.cs.cmu.edu/~dst/ARTSI/Create/PC%20Comm/ 9 | * I added Atmel's original Device dependant defines section back into 10 | *USI_TWI_Master.h 11 | * 12 | * 13 | * NOTE! - It's very important to use pullups on the SDA & SCL lines! More so 14 | *than with the Wire lib. 15 | * 16 | * USAGE is modeled after the standard Wire library . . . 17 | * Put in setup(): 18 | * TinyWireM.begin(){ // initialize I2C lib 19 | * To Send: 20 | * TinyWireM.beginTransmission(uint8_t slaveAddr){ // setup slave's 21 | *address (7 bit address - same as Wire) TinyWireM.send(uint8_t data){ // buffer 22 | *up bytes to send - can be called multiple times someByte = 23 | *TinyWireM.endTransmission(){ // actually send the bytes in the buffer 24 | * // returns (optional) 0 25 | *= sucess or see USI_TWI_Master.h for error codes To Receive: someByte = 26 | *TinyWireM.requestFrom(uint8_t slaveAddr, uint8_t numBytes){ // reads 27 | *'numBytes' from slave's address 28 | * // (usage optional) 29 | *returns 0= success or see USI_TWI_Master.h for error codes someByte = 30 | *TinyWireM.receive(){ // returns the next byte in the received 31 | *buffer - called multiple times someByte = TinyWireM.available(){ // returns 32 | *the number of unread bytes in the received buffer 33 | * 34 | * TODO: (by others!) 35 | * - merge this class with TinyWireS for master & slave support in one 36 | *library 37 | * 38 | * This library is free software; you can redistribute it and/or modify it 39 | *under the terms of the GNU General Public License as published by the Free 40 | *Software Foundation; either version 2.1 of the License, or any later version. 41 | * This program is distributed in the hope that it will be useful, but WITHOUT 42 | *ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS 43 | *FOR A PARTICULAR PURPOSE. See the GNU General Public License for more 44 | *details. 45 | */ 46 | 47 | #ifndef TinyWireM_h 48 | #define TinyWireM_h 49 | 50 | #include "Arduino.h" 51 | #include 52 | #define USI_SEND 0 //!< indicates sending to TWI 53 | #define USI_RCVE 1 //!< indicates receiving from TWI 54 | #define USI_BUF_SIZE 18 //!< bytes in message buffer 55 | 56 | /*! 57 | * @brief class USI_TWI : public Stream 58 | */ 59 | class USI_TWI { 60 | private: 61 | static uint8_t USI_Buf[]; // holds I2C send and receive data 62 | static uint8_t USI_BufIdx; // current number of bytes in the send buff 63 | static uint8_t USI_LastRead; // number of bytes read so far 64 | static uint8_t USI_BytesAvail; // number of bytes requested but not read 65 | 66 | public: 67 | USI_TWI(); 68 | /*! 69 | * @brief Initialize library for main function 70 | */ 71 | void begin(); 72 | /*! 73 | * @brief Setup address & write bit 74 | * @param slaveAddr Secondary device address 75 | */ 76 | void beginTransmission(uint8_t); 77 | /*! 78 | * @brief Buffers up data to send 79 | * @param data Data to send 80 | * @return Returns 1 when successful 81 | */ 82 | size_t write(uint8_t); 83 | /*! 84 | * @brief Sends data 85 | * @param d Data buffer 86 | * @param n How much data to send 87 | * @return Returns 1 when successful 88 | */ 89 | inline size_t write(uint8_t *d, uint8_t n) { 90 | uint16_t i; 91 | for (i = 0; i < n; i++) 92 | write(d[i]); 93 | return (size_t)n; 94 | } 95 | /*! 96 | * @brief Sends data 97 | * @param n Data to send 98 | * @return Returns 1 when successful 99 | */ 100 | inline size_t write(unsigned long n) { return write((uint8_t)n); } 101 | /*! 102 | * @brief Sends data 103 | * @param n Data to send 104 | * @return Returns 1 when successful 105 | */ 106 | inline size_t write(long n) { return write((uint8_t)n); } 107 | /*! 108 | * @brief Sends data 109 | * @param n Data to send 110 | * @return Returns 1 when successful 111 | */ 112 | inline size_t write(unsigned int n) { return write((uint8_t)n); } 113 | /*! 114 | * @brief Sends data 115 | * @param n Data to send 116 | * @return Returns 1 when successful 117 | */ 118 | inline size_t write(int n) { return write((uint8_t)n); } 119 | /*! 120 | * @brief Buffers up data to send 121 | * @param b Data to send 122 | * @return Returns 1 when successful 123 | */ 124 | void send(uint8_t b) { write(b); } 125 | /*! 126 | * @brief Sends data 127 | * @param d Buffer to send from 128 | * @param n How much to send from buffer 129 | * @return Returns 1 when successful 130 | */ 131 | void send(uint8_t *d, uint8_t n) { write(d, n); } 132 | /*! 133 | * @brief Sends data 134 | * @param n Data to send 135 | * @return Returns 1 when successful 136 | */ 137 | void send(int n) { write((uint8_t)n); } 138 | /*! 139 | * @brief Ends the transmission 140 | * @return Returns the error code if there was one 141 | */ 142 | uint8_t endTransmission(); 143 | /*! 144 | * @brief Ends the transmission 145 | * @param stop Buffer to send to end the transmission 146 | * @return Returns the error code if there was one 147 | */ 148 | uint8_t endTransmission(uint8_t); 149 | /*! 150 | * @brief Setup for receiving from secondary 151 | * @param slaveAddr Secondary device address 152 | * @param numBytes How many bytes to request 153 | * @return Returns 0, if there was an error, returns the error code 154 | */ 155 | uint8_t requestFrom(uint8_t, uint8_t); 156 | /*! 157 | * @brief Returns the bytes received one at a time 158 | * @return Returns the bytes received one at a time 159 | */ 160 | int read(); 161 | /*! 162 | * @brief The bytes available htat haven't been read yet 163 | * @return Returns how many bytes are available 164 | */ 165 | int available(); 166 | /*! 167 | * @brief Returns the top value 168 | * @return Returns the top value 169 | */ 170 | int peek(void); 171 | /*! 172 | * @brief Flushes the buffer 173 | */ 174 | void flush(void); 175 | /*! 176 | * @brief Receives data from the device 177 | * @return Returns the data 178 | */ 179 | uint8_t receive(void) { 180 | int c = read(); 181 | if (c < 0) 182 | return 0; 183 | return c; 184 | } 185 | }; 186 | 187 | extern USI_TWI TinyWireM; 188 | 189 | #endif 190 | -------------------------------------------------------------------------------- /lib/TinyWireM-master/USI_TWI_Master.cpp: -------------------------------------------------------------------------------- 1 | /*! 2 | * @file USI_TWI_Master.cpp 3 | */ 4 | /***************************************************************************** 5 | * 6 | * 7 | * File USI_TWI_Master.c compiled with gcc 8 | * Date Friday, 10/31/08 Boo! 9 | * Updated by jkl 10 | * 11 | 12 | * AppNote : AVR310 - Using the USI module as a TWI Master 13 | * 14 | * Extensively modified to provide complete I2C driver. 15 | * 16 | *Notes: 17 | * - T4_TWI and T2_TWI delays are modified to work with 1MHz 18 | default clock * and now use hard code values. They would need to 19 | change * for other clock rates. Refer to the Apps Note. 20 | * 21 | * 12/17/08 Added USI_TWI_Start_Memory_Read Routine -jkl 22 | * Note msg buffer will have slave adrs ( with write bit set) and 23 | memory adrs; 24 | * length should be these two bytes plus the number of 25 | bytes to read. 26 | ****************************************************************************/ 27 | #include "USI_TWI_Master.h" 28 | #include 29 | #include 30 | #include 31 | 32 | /*! 33 | * @brief USI Transmit and receive function 34 | * @param msg Pointer to the location of the msg buffer 35 | * @param msgSize How much data to send from the buffer 36 | * @return Returns true if transmission was successful 37 | */ 38 | unsigned char USI_TWI_Start_Transceiver_With_Data(unsigned char *, 39 | unsigned char); 40 | unsigned char USI_TWI_Master_Transfer(unsigned char); 41 | unsigned char USI_TWI_Master_Start(void); 42 | 43 | /*! 44 | * @brief Stores the state of the USI_TWI 45 | */ 46 | union USI_TWI_state { 47 | unsigned char errorState; //!< Can reuse the TWI_state for error states since 48 | //!< it will not be needed if there is an error. 49 | /*! 50 | * @brief Struct that stores the modes for the device 51 | */ 52 | struct { 53 | unsigned char addressMode : 1; //!< Address mode 54 | unsigned char masterWriteDataMode : 1; //!< Write data mode 55 | unsigned char memReadMode : 1; //!< Read memory mode 56 | unsigned char unused : 5; //!< Unused 57 | }; 58 | } USI_TWI_state; //!< USI_TWI_state The state of the USI_TWI 59 | 60 | /*! 61 | * @brief USI TWI single master initialization function 62 | */ 63 | void USI_TWI_Master_Initialise(void) { 64 | PORT_USI |= 65 | (1 66 | << PIN_USI_SDA); // Enable pullup on SDA, to set high as released state. 67 | PORT_USI |= 68 | (1 69 | << PIN_USI_SCL); // Enable pullup on SCL, to set high as released state. 70 | 71 | DDR_USI |= (1 << PIN_USI_SCL); // Enable SCL as output. 72 | DDR_USI |= (1 << PIN_USI_SDA); // Enable SDA as output. 73 | 74 | USIDR = 0xFF; // Preload dataregister with "released level" data. 75 | USICR = (0 << USISIE) | (0 << USIOIE) | // Disable Interrupts. 76 | (1 << USIWM1) | (0 << USIWM0) | // Set USI in Two-wire mode. 77 | (1 << USICS1) | (0 << USICS0) | 78 | (1 << USICLK) | // Software stobe as counter clock source 79 | (0 << USITC); 80 | USISR = (1 << USISIF) | (1 << USIOIF) | (1 << USIPF) | 81 | (1 << USIDC) | // Clear flags, 82 | (0x0 << USICNT0); // and reset counter. 83 | } 84 | 85 | /*! 86 | * @brief Use this function to get hold of the error message from the last 87 | * transmission 88 | * @return Returns error state 89 | */ 90 | unsigned char USI_TWI_Get_State_Info(void) { 91 | return (USI_TWI_state.errorState); // Return error state. 92 | } 93 | /*! 94 | * @brief USI Random (memory) Read function. This function sets up for call 95 | * to USI_TWI_Start_Transceiver_With_Data which does the work. 96 | * Doesn't matter if read/write bit is set or cleared, it'll be set 97 | * correctly in this function. 98 | * 99 | * The msgSize is passed to USI_TWI_Start_Transceiver_With_Data. 100 | * 101 | * Success or error code is returned. Error codes are defined in 102 | * USI_TWI_Master.h 103 | * @param msg Pointer to the buffer that contains the messages to be read 104 | * @param msgSize How much to read from the buffer 105 | * @return Returns the message read 106 | */ 107 | unsigned char USI_TWI_Start_Random_Read(unsigned char *msg, 108 | unsigned char msgSize) { 109 | *(msg) &= ~(TRUE << TWI_READ_BIT); // clear the read bit if it's set 110 | USI_TWI_state.errorState = 0; 111 | USI_TWI_state.memReadMode = TRUE; 112 | 113 | return (USI_TWI_Start_Transceiver_With_Data(msg, msgSize)); 114 | } 115 | /*! 116 | * @brief USI Normal Read / Write Function 117 | * Transmit and receive function. LSB of first byte in buffer 118 | * indicates if a read or write cycles is performed. If set a read 119 | * operation is performed. 120 | * 121 | * Function generates (Repeated) Start Condition, sends address and 122 | * R/W, Reads/Writes Data, and verifies/sends ACK. 123 | * 124 | * Success or error code is returned. Error codes are defined in 125 | * USI_TWI_Master.h 126 | * @param msg Pointer to the buffer that has the messages 127 | * @param msgSize The size of the message 128 | * @return Returns the data read 129 | */ 130 | unsigned char USI_TWI_Start_Read_Write(unsigned char *msg, 131 | unsigned char msgSize) { 132 | 133 | USI_TWI_state.errorState = 0; // Clears all mode bits also 134 | 135 | return (USI_TWI_Start_Transceiver_With_Data(msg, msgSize)); 136 | } 137 | /*! 138 | * @brief USI Transmit and receive function. LSB of first byte in buffer 139 | * indicates if a read or write cycles is performed. If set a read 140 | * operation is performed. 141 | * 142 | * Function generates (Repeated) Start Condition, sends address and 143 | * R/W, Reads/Writes Data, and verifies/sends ACK. 144 | * 145 | * This function also handles Random Read function if the memReadMode 146 | * bit is set. In that case, the function will: 147 | * The address in memory will be the second 148 | * byte and is written *without* sending a STOP. 149 | * Then the Read bit is set (lsb of first byte), the byte count is 150 | * adjusted (if needed), and the function function starts over by sending 151 | * the slave address again and reading the data. 152 | * 153 | * Success or error code is returned. Error codes are defined in 154 | * USI_TWI_Master.h 155 | * @param msg Pointer to the location of the msg buffer 156 | * @param msgSize How much data to send from the buffer 157 | */ 158 | unsigned char USI_TWI_Start_Transceiver_With_Data(unsigned char *msg, 159 | unsigned char msgSize) { 160 | unsigned char const tempUSISR_8bit = 161 | (1 << USISIF) | (1 << USIOIF) | (1 << USIPF) | 162 | (1 << USIDC) | // Prepare register value to: Clear flags, and 163 | (0x0 << USICNT0); // set USI to shift 8 bits i.e. count 16 clock edges. 164 | unsigned char const tempUSISR_1bit = 165 | (1 << USISIF) | (1 << USIOIF) | (1 << USIPF) | 166 | (1 << USIDC) | // Prepare register value to: Clear flags, and 167 | (0xE << USICNT0); // set USI to shift 1 bit i.e. count 2 clock edges. 168 | unsigned char *savedMsg; 169 | unsigned char savedMsgSize; 170 | 171 | // This clear must be done before calling this function so that memReadMode 172 | // can be specified. 173 | // USI_TWI_state.errorState = 0; // Clears all 174 | // mode bits also 175 | 176 | USI_TWI_state.addressMode = TRUE; // Always true for first byte 177 | 178 | #ifdef PARAM_VERIFICATION 179 | if (msg > (unsigned char *)RAMEND) // Test if address is outside SRAM space 180 | { 181 | USI_TWI_state.errorState = USI_TWI_DATA_OUT_OF_BOUND; 182 | return (FALSE); 183 | } 184 | if (msgSize <= 1) // Test if the transmission buffer is empty 185 | { 186 | USI_TWI_state.errorState = USI_TWI_NO_DATA; 187 | return (FALSE); 188 | } 189 | #endif 190 | 191 | #ifdef NOISE_TESTING // Test if any unexpected conditions have arrived prior to 192 | // this execution. 193 | if (USISR & (1 << USISIF)) { 194 | USI_TWI_state.errorState = USI_TWI_UE_START_CON; 195 | return (FALSE); 196 | } 197 | if (USISR & (1 << USIPF)) { 198 | USI_TWI_state.errorState = USI_TWI_UE_STOP_CON; 199 | return (FALSE); 200 | } 201 | if (USISR & (1 << USIDC)) { 202 | USI_TWI_state.errorState = USI_TWI_UE_DATA_COL; 203 | return (FALSE); 204 | } 205 | #endif 206 | 207 | if (!(*msg & 208 | (1 << TWI_READ_BIT))) // The LSB in the address byte determines if is a 209 | // masterRead or masterWrite operation. 210 | { 211 | USI_TWI_state.masterWriteDataMode = TRUE; 212 | } 213 | 214 | // if (USI_TWI_state.memReadMode) 215 | // { 216 | savedMsg = msg; 217 | savedMsgSize = msgSize; 218 | // } 219 | 220 | if (!USI_TWI_Master_Start()) { 221 | return (FALSE); // Send a START condition on the TWI bus. 222 | } 223 | 224 | /*Write address and Read/Write data */ 225 | do { 226 | /* If masterWrite cycle (or inital address tranmission)*/ 227 | if (USI_TWI_state.addressMode || USI_TWI_state.masterWriteDataMode) { 228 | /* Write a byte */ 229 | PORT_USI &= ~(1 << PIN_USI_SCL); // Pull SCL LOW. 230 | USIDR = *(msg++); // Setup data. 231 | USI_TWI_Master_Transfer(tempUSISR_8bit); // Send 8 bits on bus. 232 | 233 | /* Clock and verify (N)ACK from slave */ 234 | DDR_USI &= ~(1 << PIN_USI_SDA); // Enable SDA as input. 235 | if (USI_TWI_Master_Transfer(tempUSISR_1bit) & (1 << TWI_NACK_BIT)) { 236 | if (USI_TWI_state.addressMode) 237 | USI_TWI_state.errorState = USI_TWI_NO_ACK_ON_ADDRESS; 238 | else 239 | USI_TWI_state.errorState = USI_TWI_NO_ACK_ON_DATA; 240 | return (FALSE); 241 | } 242 | 243 | if ((!USI_TWI_state.addressMode) && 244 | USI_TWI_state 245 | .memReadMode) // means memory start address has been written 246 | { 247 | msg = savedMsg; // start at slave address again 248 | *(msg) |= (TRUE << TWI_READ_BIT); // set the Read Bit on Slave address 249 | USI_TWI_state.errorState = 0; 250 | USI_TWI_state.addressMode = TRUE; // Now set up for the Read cycle 251 | msgSize = savedMsgSize; // Set byte count correctly 252 | // NOte that the length should be Slave adrs byte + # bytes to read + 1 253 | // (gets decremented below) 254 | if (!USI_TWI_Master_Start()) { 255 | USI_TWI_state.errorState = USI_TWI_BAD_MEM_READ; 256 | return (FALSE); // Send a START condition on the TWI bus. 257 | } 258 | } else { 259 | USI_TWI_state.addressMode = 260 | FALSE; // Only perform address transmission once. 261 | } 262 | } 263 | /* Else masterRead cycle*/ 264 | else { 265 | /* Read a data byte */ 266 | DDR_USI &= ~(1 << PIN_USI_SDA); // Enable SDA as input. 267 | *(msg++) = USI_TWI_Master_Transfer(tempUSISR_8bit); 268 | 269 | /* Prepare to generate ACK (or NACK in case of End Of Transmission) */ 270 | if (msgSize == 1) // If transmission of last byte was performed. 271 | { 272 | USIDR = 0xFF; // Load NACK to confirm End Of Transmission. 273 | } else { 274 | USIDR = 0x00; // Load ACK. Set data register bit 7 (output for SDA) low. 275 | } 276 | USI_TWI_Master_Transfer(tempUSISR_1bit); // Generate ACK/NACK. 277 | } 278 | } while (--msgSize); // Until all data sent/received. 279 | 280 | // usually a stop condition is sent here, but TinyWireM needs to choose 281 | // whether or not to send it 282 | 283 | /* Transmission successfully completed*/ 284 | return (TRUE); 285 | } 286 | 287 | /*! 288 | * @brief Core function for shifting data in and out from the USI. 289 | * Data to be sent has to be placed into the USIDR prior to calling 290 | * this function. Data read, will be return'ed from the function. 291 | * @param temp Temperature to set the USISR 292 | * @return Returns the temp read from the device 293 | */ 294 | unsigned char USI_TWI_Master_Transfer(unsigned char temp) { 295 | USISR = temp; // Set USISR according to temp. 296 | // Prepare clocking. 297 | temp = (0 << USISIE) | (0 << USIOIE) | // Interrupts disabled 298 | (1 << USIWM1) | (0 << USIWM0) | // Set USI in Two-wire mode. 299 | (1 << USICS1) | (0 << USICS0) | 300 | (1 << USICLK) | // Software clock strobe as source. 301 | (1 << USITC); // Toggle Clock Port. 302 | do { 303 | _delay_us(T2_TWI); 304 | USICR = temp; // Generate positve SCL edge. 305 | while (!(PIN_USI & (1 << PIN_USI_SCL))) 306 | ; // Wait for SCL to go high. 307 | _delay_us(T4_TWI); 308 | USICR = temp; // Generate negative SCL edge. 309 | } while (!(USISR & (1 << USIOIF))); // Check for transfer complete. 310 | 311 | _delay_us(T2_TWI); 312 | temp = USIDR; // Read out data. 313 | USIDR = 0xFF; // Release SDA. 314 | DDR_USI |= (1 << PIN_USI_SDA); // Enable SDA as output. 315 | 316 | return temp; // Return the data from the USIDR 317 | } 318 | /*! 319 | * @brief Function for generating a TWI Start Condition. 320 | * @return Returns true if the signal can be verified, otherwise returns false 321 | */ 322 | unsigned char USI_TWI_Master_Start(void) { 323 | /* Release SCL to ensure that (repeated) Start can be performed */ 324 | PORT_USI |= (1 << PIN_USI_SCL); // Release SCL. 325 | while (!(PORT_USI & (1 << PIN_USI_SCL))) 326 | ; // Verify that SCL becomes high. 327 | _delay_us(T2_TWI); 328 | 329 | /* Generate Start Condition */ 330 | PORT_USI &= ~(1 << PIN_USI_SDA); // Force SDA LOW. 331 | _delay_us(T4_TWI); 332 | PORT_USI &= ~(1 << PIN_USI_SCL); // Pull SCL LOW. 333 | PORT_USI |= (1 << PIN_USI_SDA); // Release SDA. 334 | 335 | #ifdef SIGNAL_VERIFY 336 | if (!(USISR & (1 << USISIF))) { 337 | USI_TWI_state.errorState = USI_TWI_MISSING_START_CON; 338 | return (FALSE); 339 | } 340 | #endif 341 | return (TRUE); 342 | } 343 | /*! 344 | * @brief Function for generating a TWI Stop Condition. Used to release 345 | * the TWI bus. 346 | * @return Returns true if it was successful 347 | */ 348 | unsigned char USI_TWI_Master_Stop(void) { 349 | PORT_USI &= ~(1 << PIN_USI_SDA); // Pull SDA low. 350 | PORT_USI |= (1 << PIN_USI_SCL); // Release SCL. 351 | while (!(PIN_USI & (1 << PIN_USI_SCL))) 352 | ; // Wait for SCL to go high. 353 | _delay_us(T4_TWI); 354 | PORT_USI |= (1 << PIN_USI_SDA); // Release SDA. 355 | _delay_us(T2_TWI); 356 | 357 | #ifdef SIGNAL_VERIFY 358 | if (!(USISR & (1 << USIPF))) { 359 | USI_TWI_state.errorState = USI_TWI_MISSING_STOP_CON; 360 | return (FALSE); 361 | } 362 | #endif 363 | 364 | return (TRUE); 365 | } 366 | -------------------------------------------------------------------------------- /lib/TinyWireM-master/USI_TWI_Master.h: -------------------------------------------------------------------------------- 1 | /*! 2 | * @file USI_TWI_Master.h 3 | */ 4 | /***************************************************************************** 5 | * 6 | * 7 | * File USI_TWI_Master.h compiled with gcc 8 | * Date Friday, 10/31/08 Boo! 9 | * Updated by jkl 10 | * 11 | * 12 | * Supported devices : All device with USI module can be used. 13 | * The example is written for the ATtiny2313 14 | * 15 | * AppNote : AVR310 - Using the USI module as a TWI Master 16 | * 17 | * This is modified to just do I2C communication on ATtiny2313 running at 18 | * 1MHz. Fast mode is probably possible, but would need a faster clock 19 | * and has not been tested. 20 | * 21 | * 12/15/08 Added declaration of USI_TWI_Start_Memory_Read -jkl 22 | ****************************************************************************/ 23 | 24 | //********** Defines **********// 25 | 26 | // Defines controlling timing limits - SCL <= 100KHz. 27 | 28 | // For use with _delay_us() 29 | #define T2_TWI 5 //!< >4,7us 30 | #define T4_TWI 4 //!< >4,0us 31 | 32 | // Defines error code generating 33 | //#define PARAM_VERIFICATION 34 | //#define NOISE_TESTING 35 | #define SIGNAL_VERIFY //!< Verifies the signal is correct. This should probably 36 | //!< be on always. 37 | 38 | /**************************************************************************** 39 | Bit and byte definitions 40 | ****************************************************************************/ 41 | #define TWI_READ_BIT 0 //!< Bit position for R/W bit in "address byte". 42 | #define TWI_ADR_BITS \ 43 | 1 //!< Bit position for LSB of the slave address bits in the init byte. 44 | #define TWI_NACK_BIT 0 //!< Bit position for (N)ACK bit. 45 | 46 | // Note these have been renumbered from the Atmel Apps Note. Most likely errors 47 | // are now 48 | // lowest numbers so they're easily recognized as LED flashes. 49 | #define USI_TWI_NO_DATA 0x08 //!< Transmission buffer is empty 50 | #define USI_TWI_DATA_OUT_OF_BOUND \ 51 | 0x09 //!< Transmission buffer is outside SRAM space 52 | #define USI_TWI_UE_START_CON 0x07 //!< Unexpected Start Condition 53 | #define USI_TWI_UE_STOP_CON 0x06 //!< Unexpected Stop Condition 54 | #define USI_TWI_UE_DATA_COL 0x05 //!< Unexpected Data Collision (arbitration) 55 | #define USI_TWI_NO_ACK_ON_DATA 0x02 //!< The slave did not acknowledge all data 56 | #define USI_TWI_NO_ACK_ON_ADDRESS \ 57 | 0x01 //!< The slave did not acknowledge the address 58 | #define USI_TWI_MISSING_START_CON \ 59 | 0x03 //!< Generated Start Condition not detected on bus 60 | #define USI_TWI_MISSING_STOP_CON \ 61 | 0x04 //!< Generated Stop Condition not detected on bus 62 | #define USI_TWI_BAD_MEM_READ 0x0A //!< Error during external memory read 63 | 64 | // Device dependant defines ADDED BACK IN FROM ORIGINAL ATMEL .H 65 | 66 | #if defined(__AVR_AT90Mega169__) | defined(__AVR_ATmega169__) | \ 67 | defined(__AVR_AT90Mega165__) | defined(__AVR_ATmega165__) | \ 68 | defined(__AVR_ATmega325__) | defined(__AVR_ATmega3250__) | \ 69 | defined(__AVR_ATmega645__) | defined(__AVR_ATmega6450__) | \ 70 | defined(__AVR_ATmega329__) | defined(__AVR_ATmega3290__) | \ 71 | defined(__AVR_ATmega649__) | defined(__AVR_ATmega6490__) 72 | #define DDR_USI DDRE 73 | #define PORT_USI PORTE 74 | #define PIN_USI PINE 75 | #define PORT_USI_SDA PORTE5 76 | #define PORT_USI_SCL PORTE4 77 | #define PIN_USI_SDA PINE5 78 | #define PIN_USI_SCL PINE4 79 | #endif 80 | 81 | #if defined(__AVR_ATtiny25__) | defined(__AVR_ATtiny45__) | \ 82 | defined(__AVR_ATtiny85__) | defined(__AVR_AT90Tiny26__) | \ 83 | defined(__AVR_ATtiny26__) 84 | #define DDR_USI DDRB 85 | #define PORT_USI PORTB 86 | #define PIN_USI PINB 87 | #define PORT_USI_SDA PORTB0 88 | #define PORT_USI_SCL PORTB2 89 | #define PIN_USI_SDA PINB0 90 | #define PIN_USI_SCL PINB2 91 | #endif 92 | 93 | #if defined(__AVR_ATtiny84__) | defined(__AVR_ATtiny44__) 94 | #define DDR_USI DDRA 95 | #define PORT_USI PORTA 96 | #define PIN_USI PINA 97 | #define PORT_USI_SDA PORTA6 98 | #define PORT_USI_SCL PORTA4 99 | #define PIN_USI_SDA PINA6 100 | #define PIN_USI_SCL PINA4 101 | #endif 102 | 103 | #if defined(__AVR_AT90Tiny2313__) | defined(__AVR_ATtiny2313__) 104 | #define DDR_USI DDRB 105 | #define PORT_USI PORTB 106 | #define PIN_USI PINB 107 | #define PORT_USI_SDA PORTB5 108 | #define PORT_USI_SCL PORTB7 109 | #define PIN_USI_SDA PINB5 110 | #define PIN_USI_SCL PINB7 111 | #endif 112 | 113 | /* From the original .h 114 | // Device dependant defines - These for ATtiny2313. // CHANGED FOR ATtiny85 115 | 116 | #define DDR_USI DDRB 117 | #define PORT_USI PORTB 118 | #define PIN_USI PINB 119 | #define PORT_USI_SDA PORTB0 // was PORTB5 - N/U 120 | #define PORT_USI_SCL PORTB2 // was PORTB7 - N/U 121 | #define PIN_USI_SDA PINB0 // was PINB5 122 | #define PIN_USI_SCL PINB2 // was PINB7 123 | */ 124 | 125 | // General defines 126 | #define TRUE 1 //!< True 127 | #define FALSE 0 //!< False 128 | 129 | //********** Prototypes **********// 130 | 131 | void USI_TWI_Master_Initialise(void); 132 | unsigned char USI_TWI_Start_Random_Read(unsigned char *, unsigned char); 133 | unsigned char USI_TWI_Start_Read_Write(unsigned char *, unsigned char); 134 | unsigned char USI_TWI_Master_Stop(void); 135 | unsigned char USI_TWI_Get_State_Info(void); 136 | -------------------------------------------------------------------------------- /lib/TinyWireM-master/examples/Tiny85_Temp/Tiny85_Temp.pde: -------------------------------------------------------------------------------- 1 | /* ATtiny85 as an I2C Master Ex1 BroHogan 1/21/11 2 | * I2C master reading DS1621 temperature sensor. (display with leds) 3 | * SETUP: 4 | * ATtiny Pin 1 = (RESET) N/U ATtiny Pin 2 = (D3) LED3 5 | * ATtiny Pin 3 = (D4) to LED1 ATtiny Pin 4 = GND 6 | * ATtiny Pin 5 = SDA on DS1621 ATtiny Pin 6 = (D1) to LED2 7 | * ATtiny Pin 7 = SCK on DS1621 ATtiny Pin 8 = VCC (2.7-5.5V) 8 | * NOTE! - It's very important to use pullups on the SDA & SCL lines! 9 | * DS1621 wired per data sheet. This ex assumes A0-A2 are set LOW for an addeess of 0x48 10 | * TinyWireM USAGE & CREDITS: - see TinyWireM.h 11 | * NOTES: 12 | * The ATtiny85 + DS1621 draws 1.7mA @5V when leds are not on and not reading temp. 13 | * Using sleep mode, they draw .2 @5V @ idle - see http://brownsofa.org/blog/archives/261 14 | */ 15 | 16 | #include // I2C Master lib for ATTinys which use USI 17 | 18 | #define DS1621_ADDR 0x48 // 7 bit I2C address for DS1621 temperature sensor 19 | #define LED1_PIN 4 // ATtiny Pin 3 20 | #define LED2_PIN 1 // ATtiny Pin 6 21 | #define LED3_PIN 3 // ATtiny Pin 2 22 | 23 | int tempC = 0; // holds temp in C 24 | int tempF = 0; // holds temp in F 25 | 26 | 27 | void setup(){ 28 | pinMode(LED1_PIN,OUTPUT); 29 | pinMode(LED2_PIN,OUTPUT); 30 | pinMode(LED3_PIN,OUTPUT); 31 | Blink(LED1_PIN,2); // show it's alive 32 | TinyWireM.begin(); // initialize I2C lib 33 | Init_Temp(); // Setup DS1621 34 | delay (3000); 35 | } 36 | 37 | 38 | void loop(){ 39 | Get_Temp(); 40 | Blink(LED1_PIN,tempC/10); // blink 10's of temperature on LED 1 41 | delay (1000); 42 | Blink(LED2_PIN,tempC%10); // blink 1's of temperature on LED 2 43 | delay (4000); // wait a few sec before next reading 44 | } 45 | 46 | 47 | void Init_Temp(){ // Setup the DS1621 for one-shot mode 48 | TinyWireM.beginTransmission(DS1621_ADDR); 49 | TinyWireM.send(0xAC); // Access Command Register 50 | TinyWireM.send(B00000001); // Using one-shot mode for battery savings 51 | //TinyWireM.send(B00000000); // if setting continious mode for fast reads 52 | TinyWireM.endTransmission(); // Send to the slave 53 | } 54 | 55 | 56 | void Get_Temp(){ // Get the temperature from a DS1621 57 | TinyWireM.beginTransmission(DS1621_ADDR); 58 | TinyWireM.send(0xEE); // if one-shot, start conversions now 59 | TinyWireM.endTransmission(); // Send 1 byte to the slave 60 | delay(750); // if one-shot, must wait ~750 ms for conversion 61 | TinyWireM.beginTransmission(DS1621_ADDR); 62 | TinyWireM.send(0xAA); // read temperature (for either mode) 63 | TinyWireM.endTransmission(); // Send 1 byte to the slave 64 | TinyWireM.requestFrom(DS1621_ADDR,1); // Request 1 byte from slave 65 | tempC = TinyWireM.receive(); // get the temperature 66 | tempF = tempC * 9 / 5 + 32; // convert to Fahrenheit 67 | } 68 | 69 | 70 | void Blink(byte led, byte times){ // poor man's GUI 71 | for (byte i=0; i< times; i++){ 72 | digitalWrite(led,HIGH); 73 | delay (400); 74 | digitalWrite(led,LOW); 75 | delay (175); 76 | } 77 | } 78 | 79 | -------------------------------------------------------------------------------- /lib/TinyWireM-master/examples/Tiny85_Temp_LCD/Tiny85_Temp_LCD.pde: -------------------------------------------------------------------------------- 1 | /* ATtiny85 as an I2C Master Ex2 BroHogan 1/21/11 2 | * I2C master reading DS1621 temperature sensor. Display to I2C GPIO LED. 3 | * SETUP: 4 | * ATtiny Pin 1 = (RESET) N/U ATtiny Pin 2 = (D3) N/U 5 | * ATtiny Pin 3 = (D4) to LED1 ATtiny Pin 4 = GND 6 | * ATtiny Pin 5 = SDA on DS1621 & GPIO ATtiny Pin 6 = (D1) to LED2 7 | * ATtiny Pin 7 = SCK on DS1621 & GPIO ATtiny Pin 8 = VCC (2.7-5.5V) 8 | * NOTE! - It's very important to use pullups on the SDA & SCL lines! 9 | * DS1621 wired per data sheet. This ex assumes A0-A2 are set LOW for an addeess of 0x48 10 | * PCA8574A GPIO was used wired per instructions in "info" folder in the LiquidCrystal_I2C lib. 11 | * This ex assumes A0-A2 are set HIGH for an addeess of 0x3F 12 | * LiquidCrystal_I2C lib was modified for ATtiny - on Playground with TinyWireM lib. 13 | * TinyWireM USAGE & CREDITS: - see TinyWireM.h 14 | */ 15 | 16 | //#define DEBUG 17 | #include // I2C Master lib for ATTinys which use USI 18 | #include // for LCD w/ GPIO MODIFIED for the ATtiny85 19 | 20 | #define GPIO_ADDR 0x3F // (PCA8574A A0-A2 @5V) typ. A0-A3 Gnd 0x20 / 0x38 for A 21 | #define DS1621_ADDR 0x48 // 7 bit I2C address for DS1621 temperature sensor 22 | #define LED1_PIN 4 // ATtiny Pin 3 23 | #define LED2_PIN 1 // ATtiny Pin 6 24 | 25 | int tempC = 0; // holds temp in C 26 | int tempF = 0; // holds temp in F 27 | 28 | LiquidCrystal_I2C lcd(GPIO_ADDR,16,2); // set address & 16 chars / 2 lines 29 | 30 | 31 | void setup(){ 32 | #ifdef DEBUG 33 | pinMode(LED1_PIN,OUTPUT); 34 | pinMode(LED2_PIN,OUTPUT); 35 | Blink(LED1_PIN,2); // show it's alive 36 | #endif 37 | TinyWireM.begin(); // initialize I2C lib 38 | Init_Temp(); // Setup DS1621 39 | lcd.init(); // initialize the lcd 40 | lcd.backlight(); // Print a message to the LCD. 41 | lcd.print("Hello, Temp!"); 42 | delay (2000); 43 | } 44 | 45 | 46 | void loop(){ 47 | Get_Temp(); // read current temperature 48 | lcd.clear(); // display it 49 | lcd.print("C: "); 50 | lcd.print(tempC,DEC); 51 | lcd.setCursor(7,0); 52 | lcd.print("F: "); 53 | lcd.print(tempF,DEC); 54 | #ifdef DEBUG 55 | Blink(LED1_PIN,tempC/10); // blink 10's of temperature on LED 1 56 | delay (1000); 57 | Blink(LED2_PIN,tempC%10); // blink 1's of temperature on LED 2 58 | #endif 59 | delay (4000); // wait a few sec before next reading 60 | } 61 | 62 | 63 | void Init_Temp(){ // Setup the DS1621 for one-shot mode 64 | TinyWireM.beginTransmission(DS1621_ADDR); 65 | TinyWireM.send(0xAC); // Access Command Register 66 | TinyWireM.send(B00000001); // Using one-shot mode for battery savings 67 | //TinyWireM.send(B00000000); // if setting continious mode for fast reads 68 | TinyWireM.endTransmission(); // Send to the slave 69 | } 70 | 71 | 72 | void Get_Temp(){ // Get the temperature from a DS1621 73 | TinyWireM.beginTransmission(DS1621_ADDR); 74 | TinyWireM.send(0xEE); // if one-shot, start conversions now 75 | TinyWireM.endTransmission(); // Send 1 byte to the slave 76 | delay(750); // if one-shot, must wait ~750 ms for conversion 77 | TinyWireM.beginTransmission(DS1621_ADDR); 78 | TinyWireM.send(0xAA); // read temperature (for either mode) 79 | TinyWireM.endTransmission(); // Send 1 byte to the slave 80 | TinyWireM.requestFrom(DS1621_ADDR,1); // Request 1 byte from slave 81 | tempC = TinyWireM.receive(); // get the temperature 82 | tempF = tempC * 9 / 5 + 32; // convert to Fahrenheit 83 | } 84 | 85 | 86 | #ifdef DEBUG 87 | void Blink(byte led, byte times){ // poor man's GUI 88 | for (byte i=0; i< times; i++){ 89 | digitalWrite(led,HIGH); 90 | delay (400); 91 | digitalWrite(led,LOW); 92 | delay (175); 93 | } 94 | } 95 | #endif 96 | 97 | -------------------------------------------------------------------------------- /lib/TinyWireM-master/examples/Tiny85_Temp_LCD_RTC/Tiny85_Temp_LCD_RTC.pde: -------------------------------------------------------------------------------- 1 | /* ATtiny85 as an I2C Master Ex3 BroHogan 1/22/11 2 | * I2C master reading DS1621 temperature sensor & DS1307 RTC. Display to I2C GPIO LED. 3 | * SETUP: 4 | * ATtiny Pin 1 = (RESET) N/U ATtiny Pin 2 = (D3) N/U 5 | * ATtiny Pin 3 = (D4) to LED1 ATtiny Pin 4 = GND 6 | * ATtiny Pin 5 = SDA on all devices ATtiny Pin 6 = (D1) to LED2 7 | * ATtiny Pin 7 = SCK on all devices ATtiny Pin 8 = VCC (2.7-5.5V) 8 | * NOTE! - It's very important to use pullups on the SDA & SCL lines! 9 | * DS1621 wired per data sheet. This ex assumes A0-A2 are set LOW for an addeess of 0x48 10 | * DS1307 wired per data sheet. This ex assumes A0-A2 are set LOW for an addeess of 0x68 11 | * PCA8574A GPIO was used wired per instructions in "info" folder in the LiquidCrystal_I2C lib. 12 | * This ex assumes A0-A2 are set HIGH for an addeess of 0x3F 13 | * LiquidCrystal_I2C lib was modified for ATtiny - on Playground with TinyWireM lib. 14 | * TinyWireM USAGE & CREDITS: - see TinyWireM.h 15 | */ 16 | 17 | //#define DEBUG 18 | #include // I2C Master lib for ATTinys which use USI 19 | #include // for LCD w/ GPIO MODIFIED for the ATtiny85 20 | 21 | #define GPIO_ADDR 0x3F // (PCA8574A A0-A2 @5V) typ. A0-A3 Gnd 0x20 / 0x38 for A 22 | #define DS1307_ADDR 0x68 // I2C real time clock 23 | #define DS1621_ADDR 0x48 // 7 bit I2C address for DS1621 temperature sensor 24 | #define LED1_PIN 4 // ATtiny Pin 3 25 | #define LED2_PIN 1 // ATtiny Pin 6 26 | //#define HR24 true 27 | 28 | int tempC = 0; // holds temp in C 29 | int tempF = 0; // holds temp in F 30 | byte seconds,minutes,hours,day_of_week,days,months,years,PM,hour12,DST; 31 | char timeString[10]; // HH:MM 12 Hr. no AM/PM or 24 Hr (based on param) 32 | char dateString[10]; // MM/DD or DD/MM (based on param)- no year 33 | bool HR24; // 12/24 Hr Time and date 34 | 35 | LiquidCrystal_I2C lcd(GPIO_ADDR,16,2); // set address & 16 chars / 2 lines 36 | 37 | 38 | void setup(){ 39 | #ifdef DEBUG 40 | pinMode(LED1_PIN,OUTPUT); 41 | pinMode(LED2_PIN,OUTPUT); 42 | Blink(LED1_PIN,3); // show it's alive 43 | #endif 44 | TinyWireM.begin(); // initialize I2C lib 45 | Init_Temp(); // Setup DS1621 46 | lcd.init(); // initialize the lcd 47 | lcd.backlight(); // Print a message to the LCD. 48 | lcd.print("Hello, Temp!"); 49 | delay (2000); 50 | } 51 | 52 | 53 | void loop(){ 54 | Get_Temp(); // read current temperature 55 | Get_Time(); // read current time 56 | lcd.clear(); // display it 57 | lcd.print("C"); 58 | lcd.print((char)223); 59 | lcd.print(": "); 60 | lcd.print(tempC,DEC); 61 | lcd.setCursor(9,0); 62 | lcd.print("F"); 63 | lcd.print((char)223); 64 | lcd.print(": "); 65 | lcd.print(tempF,DEC); 66 | lcd.setCursor(0,1); 67 | lcd.print(timeString); 68 | lcd.setCursor(9,1); 69 | lcd.print(dateString); 70 | #ifdef DEBUG 71 | Blink(LED1_PIN,tempC/10); // blink 10's of temperature on LED 1 72 | delay (1000); 73 | Blink(LED2_PIN,tempC%10); // blink 1's of temperature on LED 2 74 | #endif 75 | HR24 = ! HR24; // flip the format 76 | delay (4000); // wait a few sec before next reading 77 | } 78 | 79 | 80 | void Init_Temp(){ // Setup the DS1621 for one-shot mode 81 | TinyWireM.beginTransmission(DS1621_ADDR); 82 | TinyWireM.send(0xAC); // Access Command Register 83 | TinyWireM.send(B00000001); // Using one-shot mode for battery savings 84 | //TinyWireM.send(B00000000); // if setting continious mode for fast reads 85 | TinyWireM.endTransmission(); // Send to the slave 86 | } 87 | 88 | 89 | void Get_Temp(){ // Get the temperature from a DS1621 90 | TinyWireM.beginTransmission(DS1621_ADDR); 91 | TinyWireM.send(0xEE); // if one-shot, start conversions now 92 | TinyWireM.endTransmission(); // Send 1 byte to the slave 93 | delay(750); // if one-shot, must wait ~750 ms for conversion 94 | TinyWireM.beginTransmission(DS1621_ADDR); 95 | TinyWireM.send(0xAA); // read temperature (for either mode) 96 | TinyWireM.endTransmission(); // Send 1 byte to the slave 97 | TinyWireM.requestFrom(DS1621_ADDR,1); // Request 1 byte from slave 98 | tempC = TinyWireM.receive(); // get the temperature 99 | tempF = tempC * 9 / 5 + 32; // convert to Fahrenheit 100 | } 101 | 102 | 103 | void Get_Time(){ // get the time and date from the DS1307 chip 104 | byte wireRet = 0; 105 | memset(timeString,0,sizeof(timeString)); // initialize the strings 106 | memset(dateString,0,sizeof(dateString)); 107 | 108 | TinyWireM.beginTransmission(DS1307_ADDR); // reset DS1307 register pointer 109 | TinyWireM.send(0); 110 | wireRet = TinyWireM.endTransmission(); 111 | if (wireRet) { // report any send esrrors 112 | lcd.clear(); 113 | lcd.print("SendError: "); 114 | lcd.print(wireRet,DEC); 115 | delay(1500); 116 | } 117 | wireRet = TinyWireM.requestFrom(DS1307_ADDR, 7); // request 7 bytes from DS1307 118 | if (wireRet) { // report any receive esrrors 119 | lcd.clear(); 120 | lcd.print("RcveError: "); 121 | lcd.print(wireRet,DEC); 122 | delay(1500); 123 | } 124 | #ifdef DEBUG 125 | lcd.clear(); 126 | lcd.print("Before Reads: "); 127 | lcd.print(TinyWireM.available(),DEC); // testing TinyWireM.available() 128 | delay(1500); 129 | #endif 130 | seconds = bcdToDec(TinyWireM.receive()); // handle the 7 bytes received 131 | minutes = bcdToDec(TinyWireM.receive()); 132 | hours = bcdToDec(TinyWireM.receive()); 133 | day_of_week = TinyWireM.receive(); 134 | days = bcdToDec(TinyWireM.receive()); 135 | months = bcdToDec(TinyWireM.receive()); 136 | years = bcdToDec(TinyWireM.receive()); 137 | #ifdef DEBUG 138 | lcd.clear(); 139 | lcd.print("After Reads: "); 140 | lcd.print(TinyWireM.available(),DEC); // testing TinyWireM.available() 141 | delay(1500); 142 | #endif 143 | // deal with AM/PM global and 12 hour clock 144 | if (hours >= 12) PM = true; 145 | else PM = false; 146 | if (hours > 12)hour12 = hours - 12; 147 | else hour12 = hours; 148 | if (hours == 0) hour12 = 12; 149 | 150 | // make time string 151 | if (HR24) AppendToString (hours,timeString); // add 24 hour time to string 152 | else AppendToString (hour12,timeString); // add 12 hour time to string 153 | strcat(timeString,":"); 154 | if (minutes < 10) strcat(timeString,"0"); 155 | AppendToString (minutes,timeString); // add MINUTES to string 156 | if (!HR24){ 157 | if (hours >= 12) strcat(timeString," PM"); // deal with AM/PM 158 | else strcat(timeString," AM"); 159 | } 160 | // make date string 161 | if (HR24)AppendToString (days,dateString); // add DAY to string 162 | else AppendToString (months,dateString); // add MONTH to string 163 | strcat(dateString,"/"); 164 | if (HR24)AppendToString (months,dateString); // add MONTH to string 165 | else AppendToString (days,dateString); // add DAY to string 166 | strcat(dateString,"/"); 167 | if (years < 10) strcat(dateString,"0"); 168 | AppendToString (years,dateString); // add YEAR to string 169 | } 170 | 171 | 172 | void AppendToString (byte bValue, char *pString){ // appends a byte to string passed 173 | char tempStr[6]; 174 | memset(tempStr,'\0',sizeof(tempStr)); 175 | itoa(bValue,tempStr,10); 176 | strcat(pString,tempStr); 177 | } 178 | 179 | 180 | byte bcdToDec(byte val) { // Convert binary coded decimal to normal decimal numbers 181 | return ((val / 16 * 10) + (val % 16)); 182 | } 183 | 184 | 185 | #ifdef DEBUG 186 | void Blink(byte led, byte times){ // poor man's GUI 187 | for (byte i=0; i< times; i++){ 188 | digitalWrite(led,HIGH); 189 | delay (400); 190 | digitalWrite(led,LOW); 191 | delay (175); 192 | } 193 | } 194 | #endif 195 | 196 | 197 | 198 | 199 | 200 | -------------------------------------------------------------------------------- /lib/TinyWireM-master/keywords.txt: -------------------------------------------------------------------------------- 1 | ####################################### 2 | # Syntax Coloring Map For TinyWireM 3 | ####################################### 4 | 5 | ####################################### 6 | # Datatypes (KEYWORD1) 7 | ####################################### 8 | 9 | ####################################### 10 | # Methods and Functions (KEYWORD2) 11 | ####################################### 12 | 13 | begin KEYWORD2 14 | beginTransmission KEYWORD2 15 | endTransmission KEYWORD2 16 | requestFrom KEYWORD2 17 | write KEYWORD2 18 | read KEYWORD2 19 | 20 | ####################################### 21 | # Instances (KEYWORD2) 22 | ####################################### 23 | 24 | TinyWireM KEYWORD2 25 | 26 | ####################################### 27 | # Constants (LITERAL1) 28 | ####################################### 29 | 30 | -------------------------------------------------------------------------------- /lib/TinyWireM-master/library.properties: -------------------------------------------------------------------------------- 1 | name=TinyWireM 2 | version=1.1.0 3 | author=Adafruit 4 | maintainer=Adafruit 5 | sentence=I2C library for Trinket and Gemma, adapted from BroHogan's code on Arduino Playground 6 | paragraph=I2C library for Trinket and Gemma, adapted from BroHogan's code on Arduino Playground 7 | category=Signal Input/Output 8 | url=https://github.com/adafruit/TinyWireM 9 | architectures=* 10 | -------------------------------------------------------------------------------- /platformio.ini: -------------------------------------------------------------------------------- 1 | ; PlatformIO Project Configuration File 2 | ; 3 | ; Build options: build flags, source filter 4 | ; Upload options: custom upload port, speed and extra flags 5 | ; Library options: dependencies, extra library storages 6 | ; Advanced options: extra scripting 7 | ; 8 | ; Please visit documentation for the other options and examples 9 | ; https://docs.platformio.org/page/projectconf.html 10 | 11 | [env:genericSTM32F103VE] 12 | platform = ststm32 13 | board = genericSTM32F103VE 14 | framework = arduino 15 | board_build.core = stm32 16 | ; upload_protocol = serial 17 | ; upload_port = COM5 18 | build_flags = -O1 #-fexceptions 19 | debug_tool = stlink 20 | 21 | [env:nucleo_f091rc] 22 | platform = ststm32 23 | board = nucleo_f091rc 24 | framework = arduino 25 | board_build.core = stm32 26 | build_flags = -O1 #-fexceptions 27 | debug_tool = stlink -------------------------------------------------------------------------------- /src/Device.cpp: -------------------------------------------------------------------------------- 1 | #include "Device.h" 2 | #include "States/Initialization.h" 3 | #include "OCPP_Client.h" 4 | 5 | Device::Device() { 6 | this->ChangeState(new Initialization); 7 | this->SetClient(new OCPP_Client(this)); 8 | } 9 | 10 | void Device::SetClient(OCPP_Client * client){ 11 | client_ = client; 12 | } 13 | 14 | void Device::AddConnector(Connector * connector) { 15 | connector_list_.emplace_back(connector); 16 | } 17 | 18 | uint8_t Device::NumConnectors() { 19 | return connector_list_.size(); 20 | } 21 | 22 | void Device::ReportConnectors() { 23 | if (connector_list_.size()>0) { 24 | for (unsigned i=0; iclient_->SendStatusNotification(connector_list_[i]->id, 27 | ChargePointErrorCodeNames[CP_ERROR_NoError], 28 | ChargePointStatusNames[CP_STATUS_Available]); 29 | delay(100); 30 | } 31 | } 32 | } 33 | 34 | void Device::ReportConnectorStateChange(int id) { 35 | this->client_->SendStatusNotification(connector_list_[id]->id, 36 | ChargePointErrorCodeNames[connector_list_[id]->error_], 37 | ChargePointStatusNames[connector_list_[id]->status_]); 38 | 39 | } 40 | 41 | void Device::ChangeState(State *state) { 42 | delete this->state_; // nullptr is ignored... they said 43 | this->state_ = state; 44 | this->state_->SetContext(this); 45 | logser.printf("changed state to %s\r\n", state->GetStateName().c_str()); 46 | } 47 | 48 | void Device::Update() { 49 | client_->Update(); 50 | } 51 | 52 | Connector * Device::GetConnector(int id) { 53 | // TODO check if connector exists 54 | return connector_list_[id]; 55 | } -------------------------------------------------------------------------------- /src/JSONParser.cpp: -------------------------------------------------------------------------------- 1 | #include "JSONParser.h" 2 | extern HardwareSerial logser; 3 | 4 | bool GetDouble(const string & msg, const string & key, double * value) { 5 | double raw_value; 6 | int result = mjson_get_number(msg.c_str(), msg.length(), key.c_str(), &raw_value); 7 | *value = raw_value; 8 | return result == 0 ? false : true; 9 | } 10 | 11 | bool GetInteger(string & msg, const string & key, int * value) { 12 | double raw_value; 13 | bool res = GetDouble(msg, key, &raw_value); 14 | *value = static_cast(raw_value); 15 | return res; 16 | } 17 | 18 | bool GetString(const string & msg, const char * key, string & value) { 19 | char buff[200]; 20 | int n = mjson_get_string(msg.c_str(), msg.length(), key, buff, sizeof(buff)); 21 | if (n > 0) { 22 | value.assign(buff, n); 23 | return true; 24 | } 25 | return false; 26 | } 27 | 28 | bool FindKey(const string & msg, const char * key) { 29 | const char *p; 30 | int sz; 31 | if (mjson_find(msg.c_str(), msg.length(), key, &p, &sz) > 0) return true; 32 | else return false; 33 | } 34 | 35 | bool GetObject(string & msg, const char * key, string & value) { 36 | const char *p; 37 | int n; 38 | if (mjson_find(msg.c_str(), msg.length(), key, &p, &n) == MJSON_TOK_OBJECT) { 39 | value.assign(p, n); 40 | return true; 41 | } 42 | else { 43 | return false; 44 | } 45 | } 46 | 47 | int check_if_frame_is_complete(char * buf, int len, string & frame) { 48 | int n = mjson(buf, len, NULL, NULL); 49 | if (n == 0) { 50 | // Not full JSON object was buffered 51 | return 0; 52 | } else if (n < 0) { 53 | //handle_error(); // Invalid JSON 54 | return -1; 55 | } else { 56 | // JSON object length is `n`. Parse, and then remove n bytes from the input 57 | frame.assign(buf, n); 58 | return 1; 59 | } 60 | } -------------------------------------------------------------------------------- /src/OCPP_Client.cpp: -------------------------------------------------------------------------------- 1 | #include "OCPP_Client.h" 2 | 3 | using std::string; 4 | extern HardwareSerial comser; 5 | extern HardwareSerial logser; 6 | 7 | 8 | OCPP_Client::OCPP_Client(Device * device): device_(device) { 9 | jsonrpc_init(NULL, NULL); 10 | pending_calls_ = new PendingCalls(this); 11 | boot_notification_req = new BootNotificationReq(); 12 | status_notification_req = new StatusNotificationReq(); 13 | start_transaction_req = new StartTransactionReq(); 14 | stop_transaction_req = new StopTransactionReq(); 15 | message = new Message(); 16 | message->SetDevice(device_); 17 | SendBootNotification(); 18 | } 19 | 20 | void OCPP_Client::SendBootNotification() { 21 | PendingCall *call = new PendingCall(boot_notification_req->Action, boot_notification_req->Payload()); 22 | SendCall(call); 23 | } 24 | 25 | void OCPP_Client::SendStatusNotification(int connector, string error, string status) { 26 | PendingCall *call = new PendingCall(status_notification_req->Action, status_notification_req->Payload(connector, error, status)); 27 | SendCall(call); 28 | } 29 | 30 | void OCPP_Client::SendStartTransaction(int connector, string idTag, int meterStart, string timestamp) { 31 | PendingCall *call = new PendingCall(start_transaction_req->Action, start_transaction_req->Payload(connector, idTag, meterStart, timestamp)); 32 | SendCall(call); 33 | } 34 | 35 | void OCPP_Client::SendStopTransaction(int meterStop, string timestamp, int transactionId, StopTransactionReason reason) { 36 | PendingCall *call = new PendingCall(stop_transaction_req->Action, stop_transaction_req->Payload(meterStop, timestamp, transactionId, reason)); 37 | SendCall(call); 38 | } 39 | 40 | void OCPP_Client::SendCall(PendingCall* call) { 41 | // send the call 42 | mjson_printf(Sender, NULL, call->format, call->MessageTypeId, call->UniqueId.c_str(), call->Action.c_str(), call->Payload.c_str()); 43 | logser.printf("sent %s with id %s, payload: %s\r\n", call->Action.c_str(), call->UniqueId.c_str(), call->Payload.c_str()); 44 | pending_calls_->StoreCall(call); 45 | } 46 | 47 | void OCPP_Client::ReSendCall(PendingCall* call) { 48 | // send the call 49 | mjson_printf(Sender, NULL, call->format, call->MessageTypeId, call->UniqueId.c_str(), call->Action.c_str(), call->Payload.c_str()); 50 | logser.printf("sent %s with id %s, payload: %s\r\n", call->Action.c_str(), call->UniqueId.c_str(), call->Payload.c_str()); 51 | } 52 | 53 | void OCPP_Client::SendCallResult(Msg & msg) { 54 | mjson_printf(Sender, NULL, "[%d, %Q, %s]\n", CALLRESULT, msg.uid.c_str(), msg.response_payload.c_str()); 55 | logser.printf("sent response with id %s, payload: %s\r\n", msg.uid.c_str(), msg.response_payload.c_str()); 56 | } 57 | 58 | int Sender(const char *frame, int frame_len, void *privdata) { 59 | return comser.write(frame, frame_len); 60 | } 61 | 62 | void OCPP_Client::Update(){ 63 | static char buf[200]; 64 | static int len; 65 | static string raw; 66 | 67 | pending_calls_->Update(); 68 | 69 | if (comser.available()) { 70 | char ch = comser.read(); 71 | buf[len++] = ch; 72 | int res = check_if_frame_is_complete(buf, len, raw); 73 | if(res>0) { 74 | logser.println(raw.c_str()); 75 | std::fill_n(buf, 200, 0); 76 | len = 0; 77 | Msg msg; 78 | msg.raw = raw; 79 | message->Handle(msg); 80 | } 81 | } 82 | } -------------------------------------------------------------------------------- /src/Requests/BootNotificationConf.cpp: -------------------------------------------------------------------------------- 1 | #include "Requests/BootNotificationConf.h" 2 | #include "rtc.h" 3 | 4 | 5 | Msg BootNotificationConf::Handle(Msg & msg) { 6 | 7 | string currentTime; 8 | if(!GetString(msg.payload, "$.currentTime", currentTime)) { 9 | logser.printf("'currentTime' key not found in payload %s\r\n", msg.payload.c_str()); 10 | return msg; 11 | } 12 | adjust_rtc(currentTime); 13 | 14 | int interval; 15 | GetInteger(msg.payload, "$.interval", &interval); //TODO 16 | 17 | string status_str; 18 | if(!GetString(msg.payload, "$.status", status_str)) { 19 | logser.println("cannot find 'status' key in payload"); 20 | return msg; 21 | } 22 | RegistrationStatus status = RegistrationStatusMap[status_str]; 23 | device_->state_->StateHandle_RegistrationStatus(status); 24 | return msg; 25 | } -------------------------------------------------------------------------------- /src/Requests/Call.cpp: -------------------------------------------------------------------------------- 1 | #include "Requests/Call.h" 2 | #include "Requests/ChangeAvailabilityReq.h" 3 | #include "Requests/RemoteStartTransactionReq.h" 4 | #include "Requests/RemoteStopTransactionReq.h" 5 | 6 | Call::Call() { 7 | ChangeAvailabilityReq_ = new ChangeAvailabilityReq(); 8 | RemoteStartTransactionReq_ = new RemoteStartTransactionReq(); 9 | RemoteStopTransactionReq_ = new RemoteStopTransactionReq(); 10 | } 11 | 12 | Msg Call::Handle(Msg & msg) { 13 | 14 | logser.println("handling CALL"); 15 | 16 | if(!GetObject(msg.raw, Payload_key, msg.payload)) { 17 | logser.printf("Payload not found in message %s\r\n", msg.raw.c_str()); 18 | return msg; 19 | } 20 | 21 | if(!GetString(msg.raw, Action_key, msg.action)) { 22 | logser.printf("Action not found in message %s\r\n", msg.raw.c_str()); 23 | return msg; 24 | } 25 | 26 | if(!GetString(msg.raw, UniqueId_key, msg.uid)) { 27 | logser.printf("UniqueId not found in message %s\r\n", msg.raw.c_str()); 28 | return msg; 29 | } 30 | MessageAction action = MessageActionNamesMap[msg.action]; 31 | logser.printf("got %s , id=%i", msg.action.c_str(), action); 32 | switch (action) { 33 | case CHANGE_AVAILABILITY: 34 | this->SetNext(ChangeAvailabilityReq_); 35 | break; 36 | case REMOTE_START_TRANSACTION: 37 | this->SetNext(RemoteStartTransactionReq_); 38 | break; 39 | case REMOTE_STOP_TRANSACTION: 40 | this->SetNext(RemoteStopTransactionReq_); 41 | break; 42 | default: 43 | logser.printf("unknown Action: %s\r\n", msg.action.c_str()); 44 | return msg; 45 | } 46 | 47 | return AbstractHandler::Handle(msg); 48 | } -------------------------------------------------------------------------------- /src/Requests/CallError.cpp: -------------------------------------------------------------------------------- 1 | #include "Requests/CallError.h" 2 | 3 | Msg CallError::Handle(Msg & msg) { 4 | logser.println("handling CALLERROR"); 5 | return msg; 6 | } -------------------------------------------------------------------------------- /src/Requests/CallResult.cpp: -------------------------------------------------------------------------------- 1 | #include "Requests/CallResult.h" 2 | #include "Requests/BootNotificationConf.h" 3 | #include "Requests/StatusNotificationConf.h" 4 | #include "Requests/StartTransactionConf.h" 5 | #include "Requests/StopTransactionConf.h" 6 | 7 | CallResult::CallResult() { 8 | BootNotificationConf_ = new BootNotificationConf(); 9 | StatusNotificationConf_ = new StatusNotificationConf(); 10 | StartTransactionConf_ = new StartTransactionConf(); 11 | StopTransactionConf_ = new StopTransactionConf(); 12 | } 13 | 14 | Msg CallResult::Handle(Msg & msg) { 15 | logser.println("handling CALLRESULT"); 16 | 17 | if(!GetString(msg.raw, UniqueId_key, msg.uid)) { 18 | logser.printf("UniqueId not found in message %s\r\n", msg.raw.c_str()); 19 | return msg; 20 | } 21 | 22 | if(!GetObject(msg.raw, Payload_key, msg.payload)) { 23 | logser.printf("Payload not found in message %s\r\n", msg.raw.c_str()); 24 | return msg; // TODO handle null 25 | } 26 | 27 | bool result = device_->client_->pending_calls_->GetCallActionWithId(msg.uid, msg.action); 28 | if (result) { 29 | // logser.printf("got result for id: %s payload: %s action: %s \r\n", id.c_str(), payload.c_str(), action_str.c_str()); 30 | MessageAction action = MessageActionNamesMap[msg.action]; 31 | switch (action) { 32 | case BOOT_NOTIFICATION: 33 | this->SetNext(BootNotificationConf_); 34 | break; 35 | case STATUS_NOTIFICATION: 36 | this->SetNext(StatusNotificationConf_); 37 | break; 38 | case START_TRANSACTION: 39 | this->SetNext(StartTransactionConf_); 40 | break; 41 | case STOP_TRANSACTION: 42 | this->SetNext(StopTransactionConf_); 43 | break; 44 | default: 45 | logser.println("Unknown action"); 46 | return msg; 47 | } 48 | return AbstractHandler::Handle(msg); 49 | } 50 | else { 51 | logser.println("Unknown response"); 52 | return msg; 53 | } 54 | } -------------------------------------------------------------------------------- /src/Requests/ChangeAvailabilityConf.cpp: -------------------------------------------------------------------------------- 1 | #include "Requests/ChangeAvailabilityConf.h" 2 | 3 | using std::string; 4 | 5 | 6 | void ChangeAvailabilityConf::SetPayload(string & payload) { 7 | char * buf = NULL; 8 | 9 | string status_str = AvailabilityStatusNames[status_]; 10 | int n = mjson_printf(&mjson_print_dynamic_buf, &buf, payload_format, 11 | "status", status_str.c_str() 12 | ); 13 | logser.printf("%i, generated payload %s\r\n", n, buf); 14 | payload.assign(buf, strlen(buf)); 15 | free(buf); 16 | } 17 | 18 | Msg ChangeAvailabilityConf::Handle(Msg & msg) { 19 | SetPayload(msg.response_payload); 20 | this->device_->client_->SendCallResult(msg); 21 | return msg; 22 | } -------------------------------------------------------------------------------- /src/Requests/ChangeAvailabilityReq.cpp: -------------------------------------------------------------------------------- 1 | #include "Requests/ChangeAvailabilityReq.h" 2 | #include "Requests/ChangeAvailabilityConf.h" 3 | 4 | Msg ChangeAvailabilityReq::Handle(Msg & msg) { //TODO change payload to OBJECT 5 | int connectorId; 6 | string availability_str; 7 | AvailabilityType availability; 8 | 9 | if (!GetInteger(msg.payload, "$.connectorId", &connectorId)){ 10 | logser.printf("'connectorId' key not found in payload %s\r\n", msg.payload.c_str()); 11 | return msg; 12 | } 13 | if (!GetString(msg.payload, "$.type", availability_str)) { 14 | logser.printf("'type' key not found in payload %s\r\n", msg.payload.c_str()); 15 | return msg; 16 | } 17 | 18 | availability = AvailabilityTypeNamesMap[availability_str]; 19 | AvailabilityStatus status = this->device_->state_->StateHandle_AvailabilityStatus(availability); 20 | this->SetNext(new ChangeAvailabilityConf(status)); 21 | return AbstractHandler::Handle(msg); 22 | 23 | } -------------------------------------------------------------------------------- /src/Requests/Message.cpp: -------------------------------------------------------------------------------- 1 | #include "Requests/Message.h" 2 | #include "Requests/CallResult.h" 3 | #include "Requests/Call.h" 4 | #include "Requests/CallError.h" 5 | 6 | using std::string; 7 | 8 | Message::Message(){ 9 | call_ = new Call(); 10 | callResult_ = new CallResult(); 11 | callerror_ = new CallError(); 12 | } 13 | 14 | Msg Message::Handle(Msg & msg) { 15 | 16 | int type; 17 | if (!GetInteger(msg.raw, MessageTypeId_key, &type)) { 18 | logser.println("message type not found"); 19 | return msg; 20 | } 21 | 22 | msg.type = static_cast(type); 23 | switch (msg.type) { 24 | case CALLRESULT: 25 | this->SetNext(callResult_); 26 | break; 27 | case CALLERROR: 28 | this->SetNext(callerror_); 29 | break; 30 | case CALL: 31 | this->SetNext(call_); 32 | break; 33 | default: 34 | logser.println("got UNDEFINED MessageType\r\n"); 35 | return msg; 36 | } 37 | return AbstractHandler::Handle(msg); 38 | } -------------------------------------------------------------------------------- /src/Requests/PendingCalls.cpp: -------------------------------------------------------------------------------- 1 | #include "Requests/PendingCalls.h" 2 | #include "OCPP_Client.h" 3 | 4 | extern HardwareSerial comser; 5 | extern HardwareSerial logser; 6 | 7 | PendingCall::PendingCall(string action, string payload): Action(action), Payload(payload) { 8 | UniqueId = GenerateUniqueId(); 9 | timestamp_ = millis(); 10 | } 11 | 12 | void PendingCalls::Update() { 13 | // logser.println(call_list_.capacity()); 14 | if (call_list_.size()>MAX_CALL_NUM) { 15 | logser.printf("size: %s - reached MAX_CALL_NUM!\r\n", call_list_.size()); 16 | PendingCall * pointer_to_deleted = *(call_list_.begin()); 17 | call_list_.erase(call_list_.begin()); 18 | delete pointer_to_deleted; 19 | } 20 | for (unsigned i=0; itimestamp_ > 5000) { 23 | if (call_list_[i]->Action == "StatusNotification") { 24 | logser.printf("notification call %s timed out...\r\n", call_list_[i]->UniqueId.c_str() ); 25 | // don't resend status notifications 26 | PendingCall * pointer_to_deleted = *(call_list_.begin()); 27 | call_list_.erase(call_list_.begin()); 28 | delete pointer_to_deleted; 29 | continue; 30 | } 31 | logser.printf("call %s timed out, resending...", call_list_[i]->UniqueId.c_str() ); 32 | this->client_->ReSendCall(call_list_[i]); 33 | call_list_[i]->timestamp_ = millis(); 34 | } 35 | // if timeout: 36 | // inc n++ 37 | // send again 38 | // if n>3 handle com issue - light fault led 39 | } 40 | } 41 | 42 | void PendingCalls::StoreCall(PendingCall * call) { 43 | call_list_.emplace_back(call); 44 | } 45 | 46 | bool PendingCalls::GetCallActionWithId(string & id, string & action) { 47 | 48 | for (unsigned i=0; iUniqueId == id) { 50 | action.assign(call_list_[i]->Action); 51 | PendingCall * pointer_to_deleted = *(call_list_.begin() + i); 52 | call_list_.erase(call_list_.begin()+i); 53 | delete pointer_to_deleted; 54 | return true; 55 | } 56 | } 57 | return false; 58 | } 59 | 60 | 61 | -------------------------------------------------------------------------------- /src/Requests/RemoteStartTransactionConf.cpp: -------------------------------------------------------------------------------- 1 | #include "Requests/RemoteStartTransactionConf.h" 2 | 3 | using std::string; 4 | 5 | 6 | void RemoteStartTransactionConf::SetPayload(string & payload) { 7 | char * buf = NULL; 8 | 9 | string status_str = RemoteStartStopStatusNames[status_]; 10 | int n = mjson_printf(&mjson_print_dynamic_buf, &buf, payload_format, 11 | "status", status_str.c_str() 12 | ); 13 | logser.printf("%i, generated payload %s\r\n", n, buf); 14 | payload.assign(buf, strlen(buf)); 15 | free(buf); 16 | } 17 | 18 | void RemoteStartTransactionConf::SetStatus(RemoteStartStopStatus status) { 19 | status_ = status; 20 | } 21 | 22 | Msg RemoteStartTransactionConf::Handle(Msg & msg) { 23 | SetPayload(msg.response_payload); 24 | this->device_->client_->SendCallResult(msg); 25 | return msg; 26 | } -------------------------------------------------------------------------------- /src/Requests/RemoteStartTransactionReq.cpp: -------------------------------------------------------------------------------- 1 | #include "Requests/RemoteStartTransactionReq.h" 2 | #include "Requests/RemoteStartTransactionConf.h" 3 | #include "rtc.h" 4 | 5 | extern HardwareSerial logser; 6 | extern HardwareSerial comser; 7 | 8 | RemoteStartTransactionReq::RemoteStartTransactionReq() { 9 | RemoteStartTransactionConf_ = new RemoteStartTransactionConf(); 10 | } 11 | 12 | Msg RemoteStartTransactionReq::Handle(Msg & msg) { //TODO change payload to OBJECT 13 | int connectorId; 14 | string idTag; 15 | RemoteStartStopStatus resp_status = REMOTE_STATUS_UNDEFINED; 16 | 17 | // check connectorId 18 | if (this->device_->NumConnectors() > 1) { 19 | if (!GetInteger(msg.payload, "$.connectorId", &connectorId)){ 20 | logser.printf("'connectorId' key not found in payload %s\r\n", msg.payload.c_str()); 21 | resp_status = REMOTE_STATUS_REJECTED; 22 | } 23 | } else { 24 | // message should not contain connectorId as this station has just 1 connector. 25 | if(!FindKey(msg.payload, "$.connectorId")) { 26 | connectorId = 0; 27 | } else { 28 | // unexpected 29 | resp_status = REMOTE_STATUS_REJECTED; 30 | logser.println("message should not contain connectorId as this station has just 1 connector\r\n"); 31 | } 32 | } 33 | 34 | if (!GetString(msg.payload, "$.idTag", idTag)) { 35 | logser.printf("'type' key not found in payload %s\r\n", msg.payload.c_str()); 36 | resp_status = REMOTE_STATUS_REJECTED; 37 | } 38 | 39 | // check if connector is inoperable 40 | //resp_status = REMOTE_STATUS_REJECTED; 41 | 42 | if(!resp_status) resp_status = REMOTE_STATUS_ACCEPTED; 43 | RemoteStartTransactionConf_->SetStatus(resp_status); 44 | this->SetNext(RemoteStartTransactionConf_); 45 | AbstractHandler::Handle(msg); 46 | 47 | // if no errors above 48 | if (resp_status == REMOTE_STATUS_ACCEPTED) { 49 | // if AuthorizeRemoteTxRequests is set 50 | // check idTag in localList 51 | // if no idTag in localList 52 | // send AuthorizationRequest 53 | // else 54 | this->device_->client_->SendStartTransaction(connectorId, idTag, 0, get_datetime_rtc()); 55 | comser.flush(); 56 | this->device_->GetConnector(connectorId)->SetStatus(CP_STATUS_Preparing, CP_ERROR_NoError); //doc p.39 A2 57 | this->device_->ReportConnectorStateChange(connectorId); 58 | } 59 | 60 | return msg; 61 | 62 | } -------------------------------------------------------------------------------- /src/Requests/RemoteStopTransactionConf.cpp: -------------------------------------------------------------------------------- 1 | #include "Requests/RemoteStopTransactionConf.h" 2 | 3 | using std::string; 4 | 5 | 6 | void RemoteStopTransactionConf::SetPayload(string & payload) { 7 | char * buf = NULL; 8 | 9 | string status_str = RemoteStartStopStatusNames[status_]; 10 | int n = mjson_printf(&mjson_print_dynamic_buf, &buf, payload_format, 11 | "status", status_str.c_str() 12 | ); 13 | logser.printf("%i, generated payload %s\r\n", n, buf); 14 | payload.assign(buf, strlen(buf)); 15 | free(buf); 16 | } 17 | 18 | void RemoteStopTransactionConf::SetStatus(RemoteStartStopStatus status) { 19 | status_ = status; 20 | } 21 | 22 | Msg RemoteStopTransactionConf::Handle(Msg & msg) { 23 | SetPayload(msg.response_payload); 24 | this->device_->client_->SendCallResult(msg); 25 | return msg; 26 | } -------------------------------------------------------------------------------- /src/Requests/RemoteStopTransactionReq.cpp: -------------------------------------------------------------------------------- 1 | #include "Requests/RemoteStopTransactionReq.h" 2 | #include "Requests/RemoteStopTransactionConf.h" 3 | #include "Requests/StopTransactionReq.h" 4 | #include "rtc.h" 5 | 6 | extern HardwareSerial logser; 7 | extern HardwareSerial comser; 8 | 9 | RemoteStopTransactionReq::RemoteStopTransactionReq() { 10 | RemoteStopTransactionConf_ = new RemoteStopTransactionConf(); 11 | StopTransactionReq_ = new StopTransactionReq(); 12 | } 13 | 14 | Msg RemoteStopTransactionReq::Handle(Msg & msg) { 15 | int transactionId; 16 | RemoteStartStopStatus resp_status = REMOTE_STATUS_UNDEFINED; 17 | 18 | // if payload missing transactionId 19 | if(!GetInteger(msg.payload, "$.transactionId", &transactionId)) { 20 | logser.printf("'transactionId' key not found in payload %s\r\n", msg.payload.c_str()); 21 | resp_status = REMOTE_STATUS_REJECTED; 22 | } else { 23 | // if currect transaction id matches received id 24 | int id = device_->client_->GetCurrentTransactionId(); 25 | if (id != transactionId) { 26 | logser.printf("current 'transactionId' %i doesn't match received id %i in payload %s\r\n", id, transactionId, msg.payload.c_str()); 27 | resp_status = REMOTE_STATUS_REJECTED; 28 | } 29 | } 30 | // respond with status 31 | if(!resp_status) resp_status = REMOTE_STATUS_ACCEPTED; 32 | RemoteStopTransactionConf_->SetStatus(resp_status); 33 | this->SetNext(RemoteStopTransactionConf_); 34 | AbstractHandler::Handle(msg); 35 | 36 | // if no errors above 37 | if (resp_status == REMOTE_STATUS_ACCEPTED) { 38 | logser.printf("transaction %i has stopped.\r\n", transactionId); 39 | logser.printf("\r\nCHARGING STOPPED!\r\n\r\n"); 40 | // TODO calculate meter values 41 | this->device_->client_->SendStopTransaction(this->device_->GetMeterValueForTransaction(transactionId), get_datetime_rtc(), transactionId, STOP_TRANS_REMOTE); 42 | comser.flush(); 43 | //TODO get connector which is used in this transaction 44 | this->device_->GetConnector(0)->SetStatus(CP_STATUS_Finishing, CP_ERROR_NoError); 45 | this->device_->ReportConnectorStateChange(0); 46 | } 47 | 48 | return msg; 49 | } -------------------------------------------------------------------------------- /src/Requests/StartTransactionConf.cpp: -------------------------------------------------------------------------------- 1 | #include "Requests/StartTransactionConf.h" 2 | 3 | Msg StartTransactionConf::Handle(Msg & msg) { 4 | int transactionId; 5 | string status_str; 6 | string expiryDate; 7 | /* 8 | example response: [3,"4",{"transactionId":8,"idTagInfo":{"status":"Accepted","expiryDate":"2021-02-26T13:47:44.433Z"}}] 9 | */ 10 | logser.printf("handled CallResult to %s\r\n", msg.action.c_str()); 11 | // store transaction id 12 | if (!GetInteger(msg.payload, "$.transactionId", &transactionId)){ 13 | logser.printf("'transactionId' key not found in payload %s\r\n", msg.payload.c_str()); 14 | return msg; 15 | } 16 | if(!FindKey(msg.payload, "$.idTagInfo")) { 17 | logser.printf("'idTagInfo' key not found in payload %s\r\n", msg.payload.c_str()); 18 | return msg; 19 | } 20 | if(!GetString(msg.payload, "$.idTagInfo.status", status_str)) { 21 | logser.printf("'idTagInfo.status' not found in payload %s\r\n", msg.payload.c_str()); 22 | return msg; 23 | } 24 | if(!GetString(msg.payload, "$.idTagInfo.expiryDate", expiryDate)) { 25 | logser.printf("'idTagInfo.expiryDate' not found in payload %s\r\n", msg.payload.c_str()); 26 | return msg; 27 | } 28 | // store transactionId 29 | 30 | AuthorizationStatus status = AuthorizationStatusMap[status_str]; 31 | switch (status) { 32 | case AUTH_STATUS_ACCEPTED: 33 | // Identifier is allowed for charging 34 | device_->client_->SetCurrentTransactionId(transactionId); 35 | logser.printf("\r\n\r\nTRANSACTION #%i STARTED.\r\n", transactionId); 36 | //TODO get connector which is used in this transaction 37 | this->device_->GetConnector(0)->SetStatus(CP_STATUS_Charging, CP_ERROR_NoError); 38 | this->device_->ReportConnectorStateChange(0); 39 | break; 40 | case AUTH_STATUS_BLOCKED: 41 | // Identifier has been blocked. Not allowed for charging. 42 | logser.println("got AUTH_STATUS_BLOCKED"); 43 | break; 44 | case AUTH_STATUS_EXPIRED: 45 | // Identifier has expired. Not allowed for charging. 46 | logser.println("got AUTH_STATUS_EXPIRED"); 47 | break; 48 | case AUTH_STATUS_INVALID: 49 | // Identifier is unknown. Not allowed for charging. 50 | logser.println("got AUTH_STATUS_INVALID"); 51 | break; 52 | case AUTH_STATUS_CONCURRENTTX: 53 | // Identifier is already involved in another transaction 54 | logser.println("got AUTH_STATUS_CONCURRENTTX"); 55 | break; 56 | default: 57 | logser.println("unknown AuthorizationStatus"); 58 | break; 59 | } 60 | return msg; 61 | } -------------------------------------------------------------------------------- /src/Requests/StartTransactionReq.cpp: -------------------------------------------------------------------------------- 1 | #include "Requests/StartTransactionReq.h" 2 | 3 | using std::string; 4 | 5 | string StartTransactionReq::Payload(int connector, string idTag, int meterStart, string timestamp) { 6 | char * buf = NULL; 7 | mjson_printf(&mjson_print_dynamic_buf, &buf, payload_format, 8 | "connectorId", connector, 9 | "idTag", idTag.c_str(), 10 | "meterStart", meterStart, 11 | "timestamp", timestamp.c_str() 12 | ); 13 | 14 | string payload(buf, strlen(buf)); 15 | free(buf); 16 | return payload; 17 | } 18 | -------------------------------------------------------------------------------- /src/Requests/StatusNotificationConf.cpp: -------------------------------------------------------------------------------- 1 | #include "Requests/StatusNotificationConf.h" 2 | 3 | Msg StatusNotificationConf::Handle(Msg & msg) { 4 | logser.printf("handled CallResult to %s\r\n", msg.action.c_str()); 5 | return msg; 6 | } -------------------------------------------------------------------------------- /src/Requests/StatusNotificationReq.cpp: -------------------------------------------------------------------------------- 1 | #include "Requests/StatusNotificationReq.h" 2 | using std::string; 3 | 4 | string StatusNotificationReq::Payload(int connector, string error, string status) { 5 | 6 | char * buf = NULL; 7 | mjson_printf(&mjson_print_dynamic_buf, &buf, payload_format, 8 | "connectorId", connector, 9 | "errorCode", error.c_str(), 10 | "status", status.c_str() 11 | ); 12 | 13 | string payload(buf, strlen(buf)); 14 | free(buf); 15 | return payload; 16 | } 17 | -------------------------------------------------------------------------------- /src/Requests/StopTransactionConf.cpp: -------------------------------------------------------------------------------- 1 | #include "Requests/StopTransactionConf.h" 2 | 3 | Msg StopTransactionConf::Handle(Msg & msg) { 4 | 5 | string status_str; 6 | string expiryDate; 7 | /* 8 | example response: [3,"4",{}] 9 | */ 10 | logser.printf("handled CallResult to %s\r\n", msg.action.c_str()); 11 | //TODO get connector which is used in this transaction 12 | this->device_->GetConnector(0)->SetStatus(CP_STATUS_Available, CP_ERROR_NoError); 13 | this->device_->ReportConnectorStateChange(0); 14 | return msg; 15 | } -------------------------------------------------------------------------------- /src/Requests/StopTransactionReq.cpp: -------------------------------------------------------------------------------- 1 | #include "Requests/StopTransactionReq.h" 2 | 3 | using std::string; 4 | 5 | string StopTransactionReq::Payload(int meterStop, string timestamp, int transactionId, StopTransactionReason reason) { 6 | char * buf = NULL; 7 | mjson_printf(&mjson_print_dynamic_buf, &buf, payload_format, 8 | "meterStop", meterStop, 9 | "timestamp", timestamp.c_str(), 10 | "transactionId", transactionId, 11 | "reason", StopTransactionReasonNames[reason].c_str() 12 | ); 13 | 14 | string payload(buf, strlen(buf)); 15 | free(buf); 16 | return payload; 17 | } 18 | -------------------------------------------------------------------------------- /src/Requests/bootNoticicationReq.cpp: -------------------------------------------------------------------------------- 1 | #include "Requests/BootNotificationReq.h" 2 | using std::string; 3 | 4 | string BootNotificationReq::Payload() { 5 | chargePointModel_ = "A"; // TODO 6 | chargePointVendor_ = "Y"; // TODO 7 | char * buf = NULL; 8 | mjson_printf(&mjson_print_dynamic_buf, &buf, payload_format, 9 | "chargePointVendor", chargePointVendor_.c_str(), 10 | "chargePointModel", chargePointModel_.c_str() 11 | ); 12 | 13 | string payload(buf, strlen(buf)); 14 | free(buf); 15 | return payload; 16 | } 17 | -------------------------------------------------------------------------------- /src/States/Initialization.cpp: -------------------------------------------------------------------------------- 1 | #include "States/Initialization.h" 2 | #include "States/Operative.h" 3 | 4 | const std::string Initialization::GetStateName() { 5 | return "Initialization"; 6 | } 7 | 8 | void Initialization::StateHandle_RegistrationStatus(RegistrationStatus status) { 9 | switch (status) { 10 | case ACCEPTED: 11 | logser.println("got ACCEPTED RegistrationStatus"); 12 | this->device_->ChangeState(new Operative); 13 | this->device_->ReportConnectors(); 14 | break; 15 | case PENDING: 16 | logser.println("got PENDING RegistrationStatus"); 17 | // handle this 18 | break; 19 | case REJECTED: 20 | logser.println("got REJECTED RegistrationStatus"); 21 | // handle this 22 | break; 23 | case UNDEFINED: 24 | logser.println("got UNDEFINED RegistrationStatus"); 25 | default: 26 | logser.println("unknown value for RegistrationStatus"); 27 | } 28 | } 29 | 30 | void Initialization::HandleTimerChange(){} 31 | -------------------------------------------------------------------------------- /src/States/Inoperative.cpp: -------------------------------------------------------------------------------- 1 | #include "States/Inoperative.h" 2 | #include "States/Operative.h" 3 | 4 | const std::string Inoperative::GetStateName() { 5 | return "Inoperative"; 6 | } 7 | 8 | AvailabilityStatus Inoperative::StateHandle_AvailabilityStatus(AvailabilityType type) { 9 | switch (type) { 10 | case OPERATIVE: 11 | this->device_->ChangeState(new Operative()); 12 | return AVAIL_STATUS_ACCEPTED; 13 | case INOPERATIVE: 14 | this->device_->ChangeState(new Inoperative()); 15 | return AVAIL_STATUS_ACCEPTED; 16 | default: 17 | return AVAIL_STATUS_UNDEFINED; 18 | } 19 | } 20 | 21 | void Inoperative::HandleTimerChange(){} 22 | -------------------------------------------------------------------------------- /src/States/Operative.cpp: -------------------------------------------------------------------------------- 1 | #include "States/Operative.h" 2 | #include "States/Inoperative.h" 3 | #include "OCPP_Client.h" 4 | 5 | const std::string Operative::GetStateName() { 6 | return "Operative"; 7 | } 8 | 9 | // void Operative::StateHandle_RegistrationStatus(RegistrationStatus status) { 10 | // // logser.println("already in Operative state"); 11 | // } 12 | 13 | AvailabilityStatus Operative::StateHandle_AvailabilityStatus(AvailabilityType type) { 14 | switch (type) { 15 | case OPERATIVE: 16 | this->device_->ChangeState(new Operative()); 17 | return AVAIL_STATUS_ACCEPTED; 18 | case INOPERATIVE: 19 | this->device_->ChangeState(new Inoperative()); 20 | return AVAIL_STATUS_ACCEPTED; 21 | default: 22 | return AVAIL_STATUS_UNDEFINED; 23 | } 24 | } 25 | 26 | 27 | void Operative::HandleTimerChange(){} 28 | -------------------------------------------------------------------------------- /src/States/State.cpp: -------------------------------------------------------------------------------- 1 | #include "States/State.h" 2 | 3 | uint32_t State::GetTimerValue() { 4 | return millis() - last_state_change_millis_; 5 | } 6 | 7 | void State::SetContext(Device* context) { 8 | last_state_change_millis_ = millis(); 9 | this->device_ = context; 10 | } 11 | 12 | void State::UpdateTimerValue() { 13 | last_state_change_millis_ = millis(); 14 | } -------------------------------------------------------------------------------- /src/main.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include "Device.h" 3 | #include "Connector.h" 4 | #include "rtc.h" 5 | 6 | HardwareSerial logser(PA3, PA2); 7 | 8 | //HardwareSerial comser(PA10, PA9); //for awd 9 | HardwareSerial comser(PC11, PC10); 10 | 11 | uint32_t currentTime; 12 | 13 | Device * charge_point; 14 | OCPP_Client * client; 15 | 16 | void setup() { 17 | 18 | pinMode(PA_4, OUTPUT); 19 | digitalWrite(PA_4, LOW); 20 | 21 | 22 | 23 | logser.begin(115200); 24 | comser.begin(115200); 25 | logser.println("Serial 2 up"); 26 | 27 | charge_point = new Device(); 28 | charge_point->AddConnector(new Connector(PB_0, 0)); 29 | // charge_point->AddConnector(new Connector(PB_1, 1)); 30 | 31 | init_rtc(); 32 | } 33 | 34 | void loop() { 35 | charge_point->Update(); 36 | 37 | if ((millis() - currentTime) > 3000) { 38 | currentTime = millis(); 39 | update_rtc(); 40 | //charge_point->ReportConnectors(); 41 | } 42 | } -------------------------------------------------------------------------------- /src/rtc.cpp: -------------------------------------------------------------------------------- 1 | #include "rtc.h" 2 | 3 | // Date and time functions using a DS3231 RTC connected via I2C and Wire lib 4 | 5 | extern HardwareSerial logser; 6 | RTC_DS3231 rtc; 7 | RTC_Millis rtc_millis; 8 | 9 | static char daysOfTheWeek[7][12] = {"Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"}; 10 | 11 | void init_rtc() { 12 | 13 | if (!rtc.begin(PB11, PB10)) { 14 | logser.println("Couldn't find RTC"); 15 | logser.flush(); 16 | abort(); 17 | } 18 | 19 | // if (rtc.lostPower()) { 20 | // logser.println("RTC lost power, let's set the time!"); 21 | // // When time needs to be set on a new device, or after a power loss, the 22 | // // following line sets the RTC to the date & time this sketch was compiled 23 | // rtc.adjust(DateTime(2021, 2, 26, 11, 3, 0)); 24 | // // This line sets the RTC with an explicit date & time, for example to set 25 | // // January 21, 2014 at 3am you would call: 26 | // // rtc.adjust(DateTime(2014, 1, 21, 3, 0, 0)); 27 | // } 28 | 29 | // When time needs to be re-set on a previously configured device, the 30 | // following line sets the RTC to the date & time this sketch was compiled 31 | // rtc.adjust(DateTime(F(__DATE__), F(__TIME__))); 32 | // This line sets the RTC with an explicit date & time, for example to set 33 | // January 21, 2014 at 3am you would call: 34 | // rtc.adjust(DateTime(2014, 1, 21, 3, 0, 0)); 35 | } 36 | 37 | bool adjust_rtc(string dateTime) { 38 | /* 39 | datetime format: "2021-02-26T10:14:46.751Z" 40 | */ 41 | 42 | int year = stoi(dateTime.substr(0,4)); 43 | int month = stoi(dateTime.substr(5,2)); 44 | int day = stoi(dateTime.substr(8,2)); 45 | int hour = stoi(dateTime.substr(11,4)); 46 | int minute = stoi(dateTime.substr(14,2)); 47 | int second = stoi(dateTime.substr(17,2)); 48 | 49 | logser.printf("parsed time: %i-%i-%i %i:%i:%i\r\n", year, month, day, hour, minute, second); 50 | DateTime datetime = DateTime(year, month, day, hour, minute, second); 51 | uint8_t ret = rtc.adjust(datetime); 52 | if (ret>0) { 53 | logser.printf("RTC ERROR! unable to set time!, error code=%i\r\n", ret); 54 | return false; 55 | } 56 | return true; 57 | // rtc_millis.adjust(DateTime(year, month, day, hour, minute, second)); 58 | 59 | } 60 | 61 | string get_datetime_rtc() { 62 | char buff[25] = "YYYY-MM-DDThh:mm:ss.000Z"; 63 | DateTime now = rtc.now(); 64 | now.toString(buff); 65 | //logser.printf("get_datetime_rtc: %s\r\n", buff); 66 | return string(buff, 25); 67 | } 68 | 69 | void update_rtc() { 70 | DateTime now = rtc.now(); 71 | logser.printf("%i-%i-%i %s %i:%i:%i, %u, runtime: %u \r\n", 72 | now.year(), now.month(), now.day(), daysOfTheWeek[now.dayOfTheWeek()], now.hour(), now.minute(), now.second(), now.unixtime(), millis()); // TODO handle millis rollover 73 | 74 | // calculate a date which is 7 days, 12 hours, 30 minutes, 6 seconds into the future 75 | //DateTime future (now + TimeSpan(7,12,30,6)); 76 | 77 | // Serial.print(" now + 7d + 12h + 30m + 6s: "); 78 | // Serial.print(future.year(), DEC); 79 | // Serial.print('/'); 80 | // Serial.print(future.month(), DEC); 81 | // Serial.print('/'); 82 | // Serial.print(future.day(), DEC); 83 | // Serial.print(' '); 84 | // Serial.print(future.hour(), DEC); 85 | // Serial.print(':'); 86 | // Serial.print(future.minute(), DEC); 87 | // Serial.print(':'); 88 | // Serial.print(future.second(), DEC); 89 | // Serial.println(); 90 | 91 | } 92 | --------------------------------------------------------------------------------