35 Commits

Author SHA1 Message Date
c3e50c79b5 Rebase develop 2024-01-19 16:43:37 +01:00
fe671182cd add config.ini 2024-01-19 16:40:31 +01:00
15bd7c7741 Retour Clement 2024-01-19 16:40:15 +01:00
dea01d3e84 Refacto servoMotor 2024-01-19 16:40:15 +01:00
9a8a84a59e [ServoMotor] - rework servoMotor for adding speed and easing for movement 2024-01-19 16:40:15 +01:00
027015b33b [feature/ServoMotor] - change servo librarie 2024-01-19 16:40:15 +01:00
f3dc069f3b [feature/Servo_Motor] - add ServoMotorComponent 2024-01-19 16:39:44 +01:00
1e59d9dc46 add config.ini 2024-01-19 16:37:35 +01:00
6e9a59bb00 Merge pull request 'feat: nfc-reader' (#15) from feat/nfc-reader into develop
Reviewed-on: #15
2024-01-19 12:01:17 +01:00
4023cfcb3d NFC: Removing delay function 2024-01-19 11:58:13 +01:00
0e14688f85 Merge branch 'develop' into feat/nfc-reader 2024-01-19 11:54:23 +01:00
032960c168 fix: Addr config 2024-01-19 11:51:59 +01:00
81c9ececf6 Retour Clement 2024-01-19 11:35:25 +01:00
4e8e916e5e NFC: Correcting bug & adding in config 2024-01-19 11:35:21 +01:00
a66882e877 Refacto servoMotor 2024-01-19 09:48:21 +01:00
cada4d6e02 NFC: Adding NFC Reader 2024-01-18 16:57:26 +01:00
b7fe429508 Merge pull request 'feat: GRBL-stepper-motor' (#14) from feat/GRBL-stepper into develop
Reviewed-on: #14
2024-01-18 15:46:25 +01:00
fe529b4f57 reset main to initial state 2024-01-18 15:43:04 +01:00
a924d6c534 add stepper add config 2024-01-18 15:25:33 +01:00
cfffa667b6 fix grbl lib compile 2024-01-18 15:01:41 +01:00
3c7aea15a9 [ServoMotor] - rework servoMotor for adding speed and easing for movement 2023-12-08 09:45:07 +01:00
caa5b0ceb7 feat: gestion GRBL STEPPER 2023-11-23 12:55:08 +01:00
0a43f65ce2 gestion initialisation 2023-11-23 12:05:01 +01:00
38415c2da5 change config value 2023-11-23 12:04:37 +01:00
d077deb960 main test GRBL 2023-11-17 11:17:04 +01:00
07528f75f2 add file archi 2023-11-17 11:16:41 +01:00
eb3a6426cd add stepper config 2023-11-17 11:14:26 +01:00
844cbf817c [feature/ServoMotor] - change servo librarie 2023-11-17 09:59:15 +01:00
8e8df97e68 add init fonction 2023-11-16 16:07:29 +01:00
7cf9e88995 add test stepper 2023-11-16 15:42:54 +01:00
01b99d9716 [feature/Servo_Motor] - add ServoMotorComponent 2023-11-16 09:55:30 +01:00
88077f284e Création du module DolibarrClient avec ses différentes routes & création du module WarehouseGUI pour le LCD M5Stack (#7)
Co-authored-by: Nicolas SANS <nicolas.sansd@gmail.com>
Co-authored-by: Clement <c.boesmier@aptatio.com>
Co-authored-by: Clement <clement@jo85.com>
Reviewed-on: #7
Co-authored-by: Nicolas <nicolas.sansd@gmail.com>
Co-committed-by: Nicolas <nicolas.sansd@gmail.com>
2023-11-10 16:47:39 +01:00
e4f009b63e docs: shematics (#12)
<!--
Bravo pour la PR, quelque note pour que tout se passe au mieux :D

- Lier la PR a une issue si elle existe!
- Assurez-vous que le nom de la PR respecte les règles (voir CONTRIBUTING.md)
- faites des rebase pour valider la PR
- Assurez-vous que le CI/CD est au vert
-->

Co-authored-by: Clement <c.boesmier@aptatio.com>
Reviewed-on: #12
2023-11-10 16:42:00 +01:00
258725e8c9 Feat: add doc for Dolibarr 2023-09-28 14:02:35 +02:00
884a181f04 fix: change board 2023-09-04 14:16:28 +02:00
28 changed files with 3276 additions and 8 deletions

4
.env.example Normal file
View File

@ -0,0 +1,4 @@
TIME_ZONE='Europe/Paris'
DOLI_URL='http://0.0.0.0'
DB_NAME="dolibarr"
DB_PASS="password"

2
.gitignore vendored
View File

@ -7,6 +7,8 @@
.vscode/c_cpp_properties.json
.vscode/launch.json
.vscode/ipch
.idea/
# Aptatio/Platformio specifics
secrets.ini
.env

5
.vscode/settings.json vendored Normal file
View File

@ -0,0 +1,5 @@
{
"files.associations": {
"new": "cpp"
}
}

View File

@ -13,7 +13,22 @@ build_flags =
; DO NOT TOUCH --- START
-D MONITOR_SPEED=${config.monitor_speed}
; DO NOT TOUCH --- END
-D WAITING_WIFI_DELAY=1000
-D EXAMPLE_NUMBER=69
;;;;;;;;;;;;;;;;;;;;;;
;;; stepper config ;;;
;;;;;;;;;;;;;;;;;;;;;;
-D STEPMOTOR_I2C_ADDR=0x70
-D STEPER_ACC=200
;-D STEPER_PAS=755.906 ; = 65mm
-D STEPER_PAS=58 ; = 5mm
-D STEPER_SPEED=1000 ; 12000
-D EXAMPLE_STRING=\"Pouet\"
; nfc addr
-D NFC_ADDR=0x28
;;; Servo config ;;;
;;;;;;;;;;;;;;;;;;;;;;
-D RIGHT_POS=18
-D MIDDLE_POS=32
-D LEFT_POS=52

10
config_api.ini Normal file
View File

@ -0,0 +1,10 @@
[config_api]
build_flags =
-D API_LOGIN_URL=\"/users/info\"
-D API_LIST_PRODUCT_URL=\"/products/\"
-D API_GET_PRODUCT_URL=\"/products/{id}/\"
-D API_GET_PRODUCT_STOCK_URL=\"/products/{id}/stock/\"
-D API_LIST_WAREHOUSE_URL=\"/warehouses/\"
-D API_LIST_STOCKS_MOVEMENTS_URL=\"/stockmovements/?sortfield=t.rowid\"
-D API_CREATE_STOCKS_MOVEMENTS_URL=\"/stockmovements/\"
-D API_MAX_JSON_SIZE=4096

27
docker-compose.yml Normal file
View File

@ -0,0 +1,27 @@
version: "3"
services:
mariadb:
image: mariadb:latest
environment:
MYSQL_ROOT_PASSWORD: ${DB_PASS}
MYSQL_DATABASE: ${DB_NAME}
volumes:
- database:/var/lib/mysql
restart: always
web:
image: tuxgasy/dolibarr
environment:
DOLI_DB_HOST: mariadb
DOLI_DB_USER: root
DOLI_DB_PASSWORD: ${DB_PASS}
DOLI_DB_NAME: ${DB_NAME}
DOLI_URL_ROOT: ${DOLI_URL}
PHP_INI_DATE_TIMEZONE: ${TIME_ZONE}
restart: always
# ports:
# - "80:80"
depends_on:
- mariadb
volumes:
database:

64
docs/Doc_Dolibarr.md Normal file
View File

@ -0,0 +1,64 @@
# CRM Dolibarr
## Docker Image tuxgasy/dolibarr
### Description du composant
Dolibarr est le CRM utilisé pour gérer les stocks, les transactions et l'inventaire présents dans les entrepôts. Il est le pilier central du projet et nous servira d'interface pour gérer les transactions.
### Spécifications techniques
- **Image Docker**: [tuxgasy/dolibarr](https://hub.docker.com/r/tuxgasy/dolibarr/)
- **Plugins utilisés**: Stock, API REST
- **Utilisateur technique créé**: Technical User IoT
### Fonctionnalités principales
- Créer / Lister les différents entrepôts
- Créer / Lister les produits disponibles dans un entrepôt
- Créer un mouvement dans les stocks des produits disponibles dans chaque entrepôt
- Exposer différents webservices pour automatiser certaines tâches
### Guide d'utilisation
#### Créer une instance de développement
Pour créer une instance de développement, nous allons utiliser l'image Docker de Dolibarr: [tuxgasy/dolibarr](https://hub.docker.com/r/tuxgasy/dolibarr/)
Pour simplifier l'installation, un fichier docker-compose est disponible à la racine du projet: `./docker-compose-dolibarr.yml`
Pour lancer Dolibarr, exécutez la commande suivante :
```bash
$ docker compose -f docker-compose-dolibarr.yml up
```
#### Ensuite, il faut se rendre sur [http://0.0.0.0/](http://0.0.0.0/) puis se connecter avec les identifiants par défaut (admin, admin).
### Appel des différents webservices de Dolibarr
L'URL de base pour toutes nos requêtes HTTP (avec l'image Docker) est : `http://0.0.0.0/api/index.php`
Pour commencer, récupérez l'API token d'un utilisateur pour pouvoir effectuer des requêtes API. Assurez-vous que l'utilisateur dispose des autorisations nécessaires.
Ensuite, utilisez ce token pour chaque route API en l'ajoutant dans les en-têtes : `DOLAPIKEY = {{votre_api_token}}` de votre prochaine requête.
Pour récupérer le warehouse de base et vérifier son existence :
- **Méthode**: GET
- **URL**: `warehouses/{id}`
Pour récupérer les produits disponibles :
- **Méthode**: GET
- **URL**: `products?sortfield=t.ref&sortorder=ASC&limit=10000`
Pour créer un mouvement de stock :
- **Méthode**: POST
- **URL**: `stockmovements?sortfield=t.rowid&sortorder=ASC&limit=100`
- **Body (JSON)**:
```json
{
"product_id": "1", // string, - ID du produit à déplacer
"warehouse_id": "1", // string - ID de l'entrepôt
"qty": 60, // int - quantité à déplacer (1 pour positif ou -1 pour enlever un article)
"movementcode": "S-1", // string - code du mouvement
"movementlabel": "Abc" // string - libellé du mouvement
}

View File

@ -0,0 +1,77 @@
@startuml class
hide empty members
class Dolibarr {
+ String getDestination(String tagID)
+ String createStockMovement(String tagID, String warehouseId)
}
package "Managers" {
abstract AManager {
# ILCDScreen lcd
# IServoMotor servo
# IGRBL grbl
# INFCReader nfc
}
class WarehouseManager
WarehouseManager .|> AManager
}
package "Components" {
package "NFCReader" {
interface INFCReader {
{abstract} char* read()
{abstract} bool hasTag()
}
class RC522
RC522 .|> INFCReader
}
package "LCDScreen" {
interface ILCDScreen {
{abstract} void clearScreen()
{abstract} void draw(int x, int y, int h, int w)
{abstract} void drawRect(int x, int y, int h, int w)
}
class M5LCD
M5LCD .|> ILCDScreen
}
package "GRBL" {
interface IGRBL {
{abstract} drive(int x, int y, int z, int step)
{abstract} step(int s)
}
class M5GRBL
M5GRBL .|> IGRBL
}
package "ServoMotor" {
interface IServoMotor {
{abstract} goLeft()
{abstract} goRight()
{abstract} goMiddle()
}
class ServoMotor
ServoMotor .|> IServoMotor
}
}
class Program {
+ Program()
+ void loop
}
AManager <-- IServoMotor
AManager <-- IGRBL
AManager <-- ILCDScreen
AManager <-- INFCReader
Program <-- WarehouseManager
Program <-- Dolibarr
@enduml

View File

@ -0,0 +1,22 @@
@startuml hard wiring
cloud {
[Dolibarr]
}
package "Convoyeur"{
[M5 Core]
[Lecteur NFC] as nfc
[Servo Moteur] as servo
[GRBL]
[Stepper Moteur] as Stepper
}
[Dolibarr] <-- [M5 Core] : API
[M5 Core] --> servo : IO
[M5 Core] <-- nfc : IC2
[M5 Core] --> [GRBL] : SPI
[GRBL] --> Stepper
@enduml

View File

@ -2,6 +2,9 @@
#define PROGRAM_H
#include "Arduino.h"
#include "DolibarrClient.h"
#include <M5Stack.h>
#include "ServoMotorComponent.h"
class Program {
public:
@ -11,9 +14,12 @@ public:
Program();
/**
* Program main loop
* Program WarehouseGUI loop
*/
void loop();
private:
DolibarrClient *client;
ServoMotorComponent *servo;
};
#endif

View File

@ -0,0 +1,151 @@
#include "DolibarrClient.h"
#include <WiFi.h>
#include <ArduinoJson.h>
#include <iostream>
DolibarrClient::DolibarrClient(struct DolibarrConfig dolibarr_config) : dolibarr(dolibarr_config) {
#if defined(DEBUG)
Serial.println(" --- Dolibarr configuration --- ");
Serial.println((std::string("Base URL: ") + std::string(dolibarr_config.url)).c_str());
Serial.println((std::string("Token: ") + std::string(dolibarr_config.api_key)).c_str());
#endif
this->initialize_http_client();
}
HTTPClient *DolibarrClient::build_url(const String& url) const {
auto *client = new HTTPClient();
String clientUrl = this->dolibarr.url + url;
client->begin(clientUrl);
client->addHeader("Content-Type", "application/json");
client->addHeader("DOLAPIKEY", this->dolibarr.api_key);
#if defined(DEBUG)
Serial.println("URL Request: " + clientUrl);
#endif
return client;
}
int DolibarrClient::login() const {
HTTPClient *client = this->build_url(API_LOGIN_URL);
int httpResponseCode = client->GET();
if (httpResponseCode > 0) {
StaticJsonDocument<API_MAX_JSON_SIZE> doc;
DeserializationError error = deserializeJson(doc, client->getString().c_str());
if (error) {
delete client;
return -1;
}
delete client;
return 0;
}
delete client;
return -1;
}
String replace_id(const char *str, const char *id) {
String url(str);
url.replace("{id}", id);
return url;
}
std::vector<models::Product> *DolibarrClient::list_products() const {
HTTPClient *client = this->build_url(API_LIST_PRODUCT_URL);
if (client->GET() == HTTP_CODE_OK) {
}
return nullptr;
}
models::Product *DolibarrClient::get_product_by_id(const char* id_product) const {
HTTPClient *client = this->build_url(replace_id(API_GET_PRODUCT_URL, id_product).c_str());
if (client->GET() == HTTP_CODE_OK) {
StaticJsonDocument<API_MAX_JSON_SIZE> doc;
DeserializationError error = deserializeJson(doc, client->getString().c_str());
if (error) {
Serial.println("ERROR: ");
Serial.println(error.c_str());
delete client;
return nullptr;
}
auto *product = new models::Product();
product->date_creation = doc["date_creation"];
product->id = doc["id"];
product->entity = doc["entity"];
product->stock_reel = doc["stock_reel"];
product->label = doc["label"];
delete client;
return product;
}
delete client;
return nullptr;
}
std::vector<models::Warehouse> *DolibarrClient::list_warehouse() const {
HTTPClient *client = this->build_url(API_LIST_WAREHOUSE_URL);
if (client->GET() == HTTP_CODE_OK) {
StaticJsonDocument<API_MAX_JSON_SIZE> doc;
DeserializationError error = deserializeJson(doc, client->getString().c_str());
if (error) {
Serial.println("ERROR: ");
Serial.println(error.c_str());
delete client;
return nullptr;
}
auto *warehouses = new std::vector<models::Warehouse>();
for (auto obj : doc.as<JsonArray>()) {
models::Warehouse warehouse = {};
warehouse.id = obj["id"];
warehouses->push_back(warehouse);
}
delete client;
return warehouses;
}
delete client;
return nullptr;
}
int DolibarrClient::create_movement(models::CreateProductStock &stock) const {
HTTPClient *client = this->build_url("API_CREATE_STOCKS_MOVEMENTS_URL");
StaticJsonDocument<API_MAX_JSON_SIZE> doc;
std::string result;
doc["product_id"] = stock.product_id;
doc["warehouse_id"] = stock.warehouse_id;
doc["qty"] = stock.qty;
serializeJson(doc, result);
Serial.println(result.c_str());
if (client->POST(result.c_str()) == HTTP_CODE_OK) {
delete client;
return 0;
}
return -1;
}
int DolibarrClient::initialize_http_client() {
this->httpClient = new HTTPClient();
if (this->login() == 0) {
auto* product = this->get_product_by_id("1");
if (product == nullptr) {
Serial.println("Product is nullptr !");
return -1;
}
Serial.println("Product label: ");
Serial.println(product->label);
auto* warehouses = this->list_warehouse();
if (warehouses == nullptr) {
delete product;
Serial.println("Warehouse is nullptr !");
return -1;
}
Serial.println("Warehouses: ");
models::CreateProductStock product_stock = {product->id, warehouses->at(0).id, "1"};
this->create_movement(product_stock);
for (auto warehouse : *warehouses) {
Serial.println(warehouse.id);
}
delete product;
delete warehouses;
} else {
Serial.println("An Error has occurred while trying to login");
}
return 0;
}

View File

@ -0,0 +1,35 @@
#ifndef DOLIBARR_CLIENT_H
#define DOLIBARR_CLIENT_H
#include <WiFi.h>
#include <HTTPClient.h>
#include <vector>
#include "DolibarrModels.h"
struct WifiConfig {
const char* ssid;
const char* password;
};
struct DolibarrConfig {
const char* url;
const char* api_key;
};
class DolibarrClient {
public:
DolibarrClient(DolibarrConfig dolibarr_config);
~DolibarrClient() = default;
int login() const;
std::vector<models::Warehouse> *list_warehouse() const;
std::vector<models::Product> *list_products() const;
models::Product *get_product_by_id(const char* id_product) const;
int create_movement(models::CreateProductStock &stock) const;
private:
HTTPClient* httpClient{};
struct DolibarrConfig dolibarr;
int initialize_http_client();
HTTPClient *build_url(const String& url) const;
};
#endif //DOLIBARR_CLIENT_H

View File

@ -0,0 +1,40 @@
#ifndef T_IOT_901_CONVOYOR_DOLIBARRMODELS_H
#define T_IOT_901_CONVOYOR_DOLIBARRMODELS_H
namespace models {
struct Product {
const char* id;
const char* entity;
const char* ref;
const char* status;
const char* date_creation;
const char* date_modification;
const char* label;
const char* description;
const char* type;
const char* price;
const char* stock_reel;
const char* seuil_stock_alerte;
const char* desiredstock;
};
struct ProductStock {
const char* id;
const char* product_id;
const char* quantity;
};
struct CreateProductStock {
const char* product_id;
const char* warehouse_id;
const char* qty;
};
struct Warehouse {
const char* id;
};
}
#endif //T_IOT_901_CONVOYOR_DOLIBARRMODELS_H

22
lib/GRBL/include/GRBL.h Normal file
View File

@ -0,0 +1,22 @@
#ifndef GRBL_H
#define GRBL_H
#include <Arduino.h>
#include "Module_GRBL_13.2.h"
class iGRBL{
public:
virtual void init(int speed, double pas, int accel, String mode = "distance") = 0;
virtual void mouveForward(int mm) = 0;
};
class GRBL : public iGRBL{
public:
GRBL(int grblAddr);
void init(int speed, double pas, int accel, String mode = "distance") override;
void mouveForward(int mm = 5) override;
private:
Module_GRBL* grbl;
};
#endif

34
lib/GRBL/src/GRBL.cpp Normal file
View File

@ -0,0 +1,34 @@
#include "../include/GRBL.h"
GRBL::GRBL(int grblAddr){
this->grbl = new Module_GRBL(grblAddr);
}
void GRBL::init(int speed, double pas, int accel, String mode){
char s[1024];
this->grbl->Init(&Wire);
this->grbl->setMode(mode);
sprintf(s,"$0=%f", pas); // step/mm
this->grbl->sendGcode(s);
Serial.println(s);
sprintf(s,"$4=%d", speed); // speed
this->grbl->sendGcode(s);
Serial.println(s);
sprintf(s,"$8=%d", accel); // acceleration, mm/sec^2
this->grbl->sendGcode(s);
Serial.println(s);
sprintf(s,"$3=%d", 500); // puse/µsec
this->grbl->sendGcode(s);
Serial.println(s);
}
void GRBL::mouveForward(int mm){
char s[1024];
sprintf(s, "G1 X%d", mm);
this->grbl->sendGcode(s);
}

2059
lib/NFC/src/MFRC522_I2C.cpp Normal file

File diff suppressed because it is too large Load Diff

472
lib/NFC/src/MFRC522_I2C.h Normal file
View File

@ -0,0 +1,472 @@
/**
* MFRC522_I2C.h - Library to use ARDUINO RFID MODULE KIT 13.56 MHZ WITH TAGS
*I2C BY AROZCAN MFRC522_I2C.h - Based on ARDUINO RFID MODULE KIT 13.56 MHZ WITH
*TAGS SPI Library BY COOQROBOT. Based on code Dr.Leong ( WWW.B2CQSHOP.COM )
* Created by Miguel Balboa (circuitito.com), Jan, 2012.
* Rewritten by Søren Thing Andersen (access.thing.dk), fall of 2013
*(Translation to English, refactored, comments, anti collision, cascade
*levels.) Extended by Tom Clement with functionality to write to sector 0 of
*UID changeable Mifare cards. Extended by Ahmet Remzi Ozcan with I2C
*functionality. Author: arozcan @
*https://github.com/arozcan/MFRC522-I2C-Library Released into the public
*domain.
*
* Please read this file for an overview and then MFRC522.cpp for comments on
*the specific functions. Search for "mf-rc522" on ebay.com to purchase the
*MF-RC522 board.
*
* There are three hardware components involved:
* 1) The micro controller: An Arduino
* 2) The PCD (short for Proximity Coupling Device): NXP MFRC522 Contactless
*Reader IC 3) The PICC (short for Proximity Integrated Circuit Card): A card or
*tag using the ISO 14443A interface, eg Mifare or NTAG203.
*
* The microcontroller and card reader uses I2C for communication.
* The protocol is described in the MFRC522 datasheet:
*http://www.nxp.com/documents/data_sheet/MFRC522.pdf
*
* The card reader and the tags communicate using a 13.56MHz electromagnetic
*field. The protocol is defined in ISO/IEC 14443-3 Identification cards --
*Contactless integrated circuit cards -- Proximity cards -- Part 3:
*Initialization and anticollision". A free version of the final draft can be
*found at http://wg8.de/wg8n1496_17n3613_Ballot_FCD14443-3.pdf Details are
*found in chapter 6, Type A Initialization and anticollision.
*
* If only the PICC UID is wanted, the above documents has all the needed
*information. To read and write from MIFARE PICCs, the MIFARE protocol is used
*after the PICC has been selected. The MIFARE Classic chips and protocol is
*described in the datasheets: 1K:
*http://www.nxp.com/documents/data_sheet/MF1S503x.pdf 4K:
*http://www.nxp.com/documents/data_sheet/MF1S703x.pdf Mini:
*http://www.idcardmarket.com/download/mifare_S20_datasheet.pdf The MIFARE
*Ultralight chip and protocol is described in the datasheets: Ultralight:
*http://www.nxp.com/documents/data_sheet/MF0ICU1.pdf Ultralight C:
*http://www.nxp.com/documents/short_data_sheet/MF0ICU2_SDS.pdf
*
* MIFARE Classic 1K (MF1S503x):
* Has 16 sectors * 4 blocks/sector * 16 bytes/block = 1024 bytes.
* The blocks are numbered 0-63.
* Block 3 in each sector is the Sector Trailer. See
*http://www.nxp.com/documents/data_sheet/MF1S503x.pdf sections 8.6 and 8.7:
* Bytes 0-5: Key A
* Bytes 6-8: Access Bits
* Bytes 9: User data
* Bytes 10-15: Key B (or user data)
* Block 0 is read-only manufacturer data.
* To access a block, an authentication using a key from the block's sector
*must be performed first. Example: To read from block 10, first authenticate
*using a key from sector 3 (blocks 8-11). All keys are set to FFFFFFFFFFFFh at
*chip delivery. Warning: Please read section 8.7 "Memory Access". It includes
*this text: if the PICC detects a format violation the whole sector is
*irreversibly blocked. To use a block in "value block" mode (for
*Increment/Decrement operations) you need to change the sector trailer. Use
*PICC_SetAccessBits() to calculate the bit patterns. MIFARE Classic 4K
*(MF1S703x): Has (32 sectors * 4 blocks/sector + 8 sectors * 16 blocks/sector)
** 16 bytes/block = 4096 bytes. The blocks are numbered 0-255. The last block
*in each sector is the Sector Trailer like above. MIFARE Classic Mini (MF1 IC
*S20): Has 5 sectors * 4 blocks/sector * 16 bytes/block = 320 bytes. The blocks
*are numbered 0-19. The last block in each sector is the Sector Trailer like
*above.
*
* MIFARE Ultralight (MF0ICU1):
* Has 16 pages of 4 bytes = 64 bytes.
* Pages 0 + 1 is used for the 7-byte UID.
* Page 2 contains the last check digit for the UID, one byte manufacturer
*internal data, and the lock bytes (see
*http://www.nxp.com/documents/data_sheet/MF0ICU1.pdf section 8.5.2) Page 3 is
*OTP, One Time Programmable bits. Once set to 1 they cannot revert to 0. Pages
*4-15 are read/write unless blocked by the lock bytes in page 2. MIFARE
*Ultralight C (MF0ICU2): Has 48 pages of 4 bytes = 192 bytes. Pages 0 + 1 is
*used for the 7-byte UID. Page 2 contains the last check digit for the UID, one
*byte manufacturer internal data, and the lock bytes (see
*http://www.nxp.com/documents/data_sheet/MF0ICU1.pdf section 8.5.2) Page 3 is
*OTP, One Time Programmable bits. Once set to 1 they cannot revert to 0. Pages
*4-39 are read/write unless blocked by the lock bytes in page 2. Page 40 Lock
*bytes Page 41 16 bit one way counter Pages 42-43 Authentication configuration
* Pages 44-47 Authentication key
*/
#ifndef MFRC522_h
#define MFRC522_h
#include <Arduino.h>
#include <Wire.h>
// Firmware data for self-test
// Reference values based on firmware version
// Hint: if needed, you can remove unused self-test data to save flash memory
//
// Version 0.0 (0x90)
// Philips Semiconductors; Preliminary Specification Revision 2.0 - 01 August
// 2005; 16.1 Sefttest
const byte MFRC522_firmware_referenceV0_0[] PROGMEM = {
0x00, 0x87, 0x98, 0x0f, 0x49, 0xFF, 0x07, 0x19, 0xBF, 0x22, 0x30,
0x49, 0x59, 0x63, 0xAD, 0xCA, 0x7F, 0xE3, 0x4E, 0x03, 0x5C, 0x4E,
0x49, 0x50, 0x47, 0x9A, 0x37, 0x61, 0xE7, 0xE2, 0xC6, 0x2E, 0x75,
0x5A, 0xED, 0x04, 0x3D, 0x02, 0x4B, 0x78, 0x32, 0xFF, 0x58, 0x3B,
0x7C, 0xE9, 0x00, 0x94, 0xB4, 0x4A, 0x59, 0x5B, 0xFD, 0xC9, 0x29,
0xDF, 0x35, 0x96, 0x98, 0x9E, 0x4F, 0x30, 0x32, 0x8D};
// Version 1.0 (0x91)
// NXP Semiconductors; Rev. 3.8 - 17 September 2014; 16.1.1 Self test
const byte MFRC522_firmware_referenceV1_0[] PROGMEM = {
0x00, 0xC6, 0x37, 0xD5, 0x32, 0xB7, 0x57, 0x5C, 0xC2, 0xD8, 0x7C,
0x4D, 0xD9, 0x70, 0xC7, 0x73, 0x10, 0xE6, 0xD2, 0xAA, 0x5E, 0xA1,
0x3E, 0x5A, 0x14, 0xAF, 0x30, 0x61, 0xC9, 0x70, 0xDB, 0x2E, 0x64,
0x22, 0x72, 0xB5, 0xBD, 0x65, 0xF4, 0xEC, 0x22, 0xBC, 0xD3, 0x72,
0x35, 0xCD, 0xAA, 0x41, 0x1F, 0xA7, 0xF3, 0x53, 0x14, 0xDE, 0x7E,
0x02, 0xD9, 0x0F, 0xB5, 0x5E, 0x25, 0x1D, 0x29, 0x79};
// Version 2.0 (0x92)
// NXP Semiconductors; Rev. 3.8 - 17 September 2014; 16.1.1 Self test
const byte MFRC522_firmware_referenceV2_0[] PROGMEM = {
0x00, 0xEB, 0x66, 0xBA, 0x57, 0xBF, 0x23, 0x95, 0xD0, 0xE3, 0x0D,
0x3D, 0x27, 0x89, 0x5C, 0xDE, 0x9D, 0x3B, 0xA7, 0x00, 0x21, 0x5B,
0x89, 0x82, 0x51, 0x3A, 0xEB, 0x02, 0x0C, 0xA5, 0x00, 0x49, 0x7C,
0x84, 0x4D, 0xB3, 0xCC, 0xD2, 0x1B, 0x81, 0x5D, 0x48, 0x76, 0xD5,
0x71, 0x61, 0x21, 0xA9, 0x86, 0x96, 0x83, 0x38, 0xCF, 0x9D, 0x5B,
0x6D, 0xDC, 0x15, 0xBA, 0x3E, 0x7D, 0x95, 0x3B, 0x2F};
// Clone
// Fudan Semiconductor FM17522 (0x88)
const byte FM17522_firmware_reference[] PROGMEM = {
0x00, 0xD6, 0x78, 0x8C, 0xE2, 0xAA, 0x0C, 0x18, 0x2A, 0xB8, 0x7A,
0x7F, 0xD3, 0x6A, 0xCF, 0x0B, 0xB1, 0x37, 0x63, 0x4B, 0x69, 0xAE,
0x91, 0xC7, 0xC3, 0x97, 0xAE, 0x77, 0xF4, 0x37, 0xD7, 0x9B, 0x7C,
0xF5, 0x3C, 0x11, 0x8F, 0x15, 0xC3, 0xD7, 0xC1, 0x5B, 0x00, 0x2A,
0xD0, 0x75, 0xDE, 0x9E, 0x51, 0x64, 0xAB, 0x3E, 0xE9, 0x15, 0xB5,
0xAB, 0x56, 0x9A, 0x98, 0x82, 0x26, 0xEA, 0x2A, 0x62};
class MFRC522 {
public:
// MFRC522 registers. Described in chapter 9 of the datasheet.
enum PCD_Register {
// Page 0: Command and status
// 0x00 // reserved for future use
CommandReg = 0x01, // starts and stops command execution
ComIEnReg = 0x02, // enable and disable interrupt request control bits
DivIEnReg = 0x03, // enable and disable interrupt request control bits
ComIrqReg = 0x04, // interrupt request bits
DivIrqReg = 0x05, // interrupt request bits
ErrorReg = 0x06, // error bits showing the error status of the last
// command executed
Status1Reg = 0x07, // communication status bits
Status2Reg = 0x08, // receiver and transmitter status bits
FIFODataReg = 0x09, // input and output of 64 byte FIFO buffer
FIFOLevelReg = 0x0A, // number of bytes stored in the FIFO buffer
WaterLevelReg = 0x0B, // level for FIFO underflow and overflow warning
ControlReg = 0x0C, // miscellaneous control registers
BitFramingReg = 0x0D, // adjustments for bit-oriented frames
CollReg = 0x0E, // bit position of the first bit-collision detected on
// the RF interface
// 0x0F // reserved for future use
// Page 1: Command
// 0x10 // reserved for future use
ModeReg = 0x11, // defines general modes for transmitting and receiving
TxModeReg = 0x12, // defines transmission data rate and framing
RxModeReg = 0x13, // defines reception data rate and framing
TxControlReg = 0x14, // controls the logical behavior of the antenna
// driver pins TX1 and TX2
TxASKReg = 0x15, // controls the setting of the transmission modulation
TxSelReg = 0x16, // selects the internal sources for the antenna driver
RxSelReg = 0x17, // selects internal receiver settings
RxThresholdReg = 0x18, // selects thresholds for the bit decoder
DemodReg = 0x19, // defines demodulator settings
// 0x1A // reserved for future use
// 0x1B // reserved for future use
MfTxReg =
0x1C, // controls some MIFARE communication transmit parameters
MfRxReg =
0x1D, // controls some MIFARE communication receive parameters
// 0x1E // reserved for future use
SerialSpeedReg =
0x1F, // selects the speed of the serial UART interface
// Page 2: Configuration
// 0x20 // reserved for future use
CRCResultRegH =
0x21, // shows the MSB and LSB values of the CRC calculation
CRCResultRegL = 0x22,
// 0x23 // reserved for future use
ModWidthReg = 0x24, // controls the ModWidth setting?
// 0x25 // reserved for future use
RFCfgReg = 0x26, // configures the receiver gain
GsNReg = 0x27, // selects the conductance of the antenna driver pins
// TX1 and TX2 for modulation
CWGsPReg = 0x28, // defines the conductance of the p-driver output
// during periods of no modulation
ModGsPReg = 0x29, // defines the conductance of the p-driver output
// during periods of modulation
TModeReg = 0x2A, // defines settings for the internal timer
TPrescalerReg = 0x2B, // the lower 8 bits of the TPrescaler value. The
// 4 high bits are in TModeReg.
TReloadRegH = 0x2C, // defines the 16-bit timer reload value
TReloadRegL = 0x2D,
TCounterValueRegH = 0x2E, // shows the 16-bit timer value
TCounterValueRegL = 0x2F,
// Page 3: Test Registers
// 0x30 // reserved for future use
TestSel1Reg = 0x31, // general test signal configuration
TestSel2Reg = 0x32, // general test signal configuration
TestPinEnReg = 0x33, // enables pin output driver on pins D1 to D7
TestPinValueReg = 0x34, // defines the values for D1 to D7 when it is
// used as an I/O bus
TestBusReg = 0x35, // shows the status of the internal test bus
AutoTestReg = 0x36, // controls the digital self test
VersionReg = 0x37, // shows the software version
AnalogTestReg = 0x38, // controls the pins AUX1 and AUX2
TestDAC1Reg = 0x39, // defines the test value for TestDAC1
TestDAC2Reg = 0x3A, // defines the test value for TestDAC2
TestADCReg = 0x3B // shows the value of ADC I and Q channels
// 0x3C // reserved for production tests
// 0x3D // reserved for production tests
// 0x3E // reserved for production tests
// 0x3F // reserved for production tests
};
// MFRC522 commands. Described in chapter 10 of the datasheet.
enum PCD_Command {
PCD_Idle = 0x00, // no action, cancels current command execution
PCD_Mem = 0x01, // stores 25 bytes into the internal buffer
PCD_GenerateRandomID = 0x02, // generates a 10-byte random ID number
PCD_CalcCRC =
0x03, // activates the CRC coprocessor or performs a self test
PCD_Transmit = 0x04, // transmits data from the FIFO buffer
PCD_NoCmdChange = 0x07, // no command change, can be used to modify the
// CommandReg register bits without affecting
// the command, for example, the PowerDown bit
PCD_Receive = 0x08, // activates the receiver circuits
PCD_Transceive =
0x0C, // transmits data from FIFO buffer to antenna and
// automatically activates the receiver after transmission
PCD_MFAuthent =
0x0E, // performs the MIFARE standard authentication as a reader
PCD_SoftReset = 0x0F // resets the MFRC522
};
// MFRC522 RxGain[2:0] masks, defines the receiver's signal voltage gain
// factor (on the PCD). Described in 9.3.3.6 / table 98 of the datasheet at
// http://www.nxp.com/documents/data_sheet/MFRC522.pdf
enum PCD_RxGain {
RxGain_18dB = 0x00 << 4, // 000b - 18 dB, minimum
RxGain_23dB = 0x01 << 4, // 001b - 23 dB
RxGain_18dB_2 =
0x02 << 4, // 010b - 18 dB, it seems 010b is a duplicate for 000b
RxGain_23dB_2 =
0x03 << 4, // 011b - 23 dB, it seems 011b is a duplicate for 001b
RxGain_33dB = 0x04 << 4, // 100b - 33 dB, average, and typical default
RxGain_38dB = 0x05 << 4, // 101b - 38 dB
RxGain_43dB = 0x06 << 4, // 110b - 43 dB
RxGain_48dB = 0x07 << 4, // 111b - 48 dB, maximum
RxGain_min =
0x00 << 4, // 000b - 18 dB, minimum, convenience for RxGain_18dB
RxGain_avg =
0x04 << 4, // 100b - 33 dB, average, convenience for RxGain_33dB
RxGain_max =
0x07 << 4 // 111b - 48 dB, maximum, convenience for RxGain_48dB
};
// Commands sent to the PICC.
enum PICC_Command {
// The commands used by the PCD to manage communication with several
// PICCs (ISO 14443-3, Type A, section 6.4)
PICC_CMD_REQA = 0x26, // REQuest command, Type A. Invites PICCs in
// state IDLE to go to READY and prepare for
// anticollision or selection. 7 bit frame.
PICC_CMD_WUPA =
0x52, // Wake-UP command, Type A. Invites PICCs in state IDLE and
// HALT to go to READY(*) and prepare for anticollision or
// selection. 7 bit frame.
PICC_CMD_CT = 0x88, // Cascade Tag. Not really a command, but used
// during anti collision.
PICC_CMD_SEL_CL1 = 0x93, // Anti collision/Select, Cascade Level 1
PICC_CMD_SEL_CL2 = 0x95, // Anti collision/Select, Cascade Level 2
PICC_CMD_SEL_CL3 = 0x97, // Anti collision/Select, Cascade Level 3
PICC_CMD_HLTA = 0x50, // HaLT command, Type A. Instructs an ACTIVE PICC
// to go to state HALT.
// The commands used for MIFARE Classic (from
// http://www.nxp.com/documents/data_sheet/MF1S503x.pdf, Section 9)
// Use PCD_MFAuthent to authenticate access to a sector, then use these
// commands to read/write/modify the blocks on the sector.
// The read/write commands can also be used for MIFARE Ultralight.
PICC_CMD_MF_AUTH_KEY_A = 0x60, // Perform authentication with Key A
PICC_CMD_MF_AUTH_KEY_B = 0x61, // Perform authentication with Key B
PICC_CMD_MF_READ =
0x30, // Reads one 16 byte block from the authenticated sector of
// the PICC. Also used for MIFARE Ultralight.
PICC_CMD_MF_WRITE =
0xA0, // Writes one 16 byte block to the authenticated sector of
// the PICC. Called "COMPATIBILITY WRITE" for MIFARE
// Ultralight.
PICC_CMD_MF_DECREMENT =
0xC0, // Decrements the contents of a block and stores the result
// in the internal data register.
PICC_CMD_MF_INCREMENT =
0xC1, // Increments the contents of a block and stores the result
// in the internal data register.
PICC_CMD_MF_RESTORE = 0xC2, // Reads the contents of a block into the
// internal data register.
PICC_CMD_MF_TRANSFER = 0xB0, // Writes the contents of the internal
// data register to a block.
// The commands used for MIFARE Ultralight (from
// http://www.nxp.com/documents/data_sheet/MF0ICU1.pdf, Section 8.6)
// The PICC_CMD_MF_READ and PICC_CMD_MF_WRITE can also be used for
// MIFARE Ultralight.
PICC_CMD_UL_WRITE = 0xA2 // Writes one 4 byte page to the PICC.
};
// MIFARE constants that does not fit anywhere else
enum MIFARE_Misc {
MF_ACK = 0xA, // The MIFARE Classic uses a 4 bit ACK/NAK. Any other
// value than 0xA is NAK.
MF_KEY_SIZE = 6 // A Mifare Crypto1 key is 6 bytes.
};
// PICC types we can detect. Remember to update PICC_GetTypeName() if you
// add more.
enum PICC_Type {
PICC_TYPE_UNKNOWN = 0,
PICC_TYPE_ISO_14443_4 = 1, // PICC compliant with ISO/IEC 14443-4
PICC_TYPE_ISO_18092 = 2, // PICC compliant with ISO/IEC 18092 (NFC)
PICC_TYPE_MIFARE_MINI = 3, // MIFARE Classic protocol, 320 bytes
PICC_TYPE_MIFARE_1K = 4, // MIFARE Classic protocol, 1KB
PICC_TYPE_MIFARE_4K = 5, // MIFARE Classic protocol, 4KB
PICC_TYPE_MIFARE_UL = 6, // MIFARE Ultralight or Ultralight C
PICC_TYPE_MIFARE_PLUS = 7, // MIFARE Plus
PICC_TYPE_TNP3XXX = 8, // Only mentioned in NXP AN 10833 MIFARE Type
// Identification Procedure
PICC_TYPE_NOT_COMPLETE = 255 // SAK indicates UID is not complete.
};
// Return codes from the functions in this class. Remember to update
// GetStatusCodeName() if you add more.
enum StatusCode {
STATUS_OK = 1, // Success
STATUS_ERROR = 2, // Error in communication
STATUS_COLLISION = 3, // Collission detected
STATUS_TIMEOUT = 4, // Timeout in communication.
STATUS_NO_ROOM = 5, // A buffer is not big enough.
STATUS_INTERNAL_ERROR =
6, // Internal error in the code. Should not happen ;-)
STATUS_INVALID = 7, // Invalid argument.
STATUS_CRC_WRONG = 8, // The CRC_A does not match
STATUS_MIFARE_NACK = 9 // A MIFARE PICC responded with NAK.
};
// A struct used for passing the UID of a PICC.
typedef struct {
byte size; // Number of bytes in the UID. 4, 7 or 10.
byte uidByte[10];
byte sak; // The SAK (Select acknowledge) byte returned from the PICC
// after successful selection.
} Uid;
// A struct used for passing a MIFARE Crypto1 key
typedef struct {
byte keyByte[MF_KEY_SIZE];
} MIFARE_Key;
// Member variables
Uid uid; // Used by PICC_ReadCardSerial().
// Size of the MFRC522 FIFO
static const byte FIFO_SIZE = 64; // The FIFO is 64 bytes.
/////////////////////////////////////////////////////////////////////////////////////
// Functions for setting up the Arduino
/////////////////////////////////////////////////////////////////////////////////////
MFRC522(byte chipAddress);
/////////////////////////////////////////////////////////////////////////////////////
// Basic interface functions for communicating with the MFRC522
/////////////////////////////////////////////////////////////////////////////////////
void PCD_WriteRegister(byte reg, byte value);
void PCD_WriteRegister(byte reg, byte count, byte *values);
byte PCD_ReadRegister(byte reg);
void PCD_ReadRegister(byte reg, byte count, byte *values, byte rxAlign = 0);
void setBitMask(unsigned char reg, unsigned char mask);
void PCD_SetRegisterBitMask(byte reg, byte mask);
void PCD_ClearRegisterBitMask(byte reg, byte mask);
byte PCD_CalculateCRC(byte *data, byte length, byte *result);
/////////////////////////////////////////////////////////////////////////////////////
// Functions for manipulating the MFRC522
/////////////////////////////////////////////////////////////////////////////////////
void PCD_Init();
void PCD_Reset();
void PCD_AntennaOn();
void PCD_AntennaOff();
byte PCD_GetAntennaGain();
void PCD_SetAntennaGain(byte mask);
bool PCD_PerformSelfTest();
/////////////////////////////////////////////////////////////////////////////////////
// Functions for communicating with PICCs
/////////////////////////////////////////////////////////////////////////////////////
byte PCD_TransceiveData(byte *sendData, byte sendLen, byte *backData,
byte *backLen, byte *validBits = NULL,
byte rxAlign = 0, bool checkCRC = false);
byte PCD_CommunicateWithPICC(byte command, byte waitIRq, byte *sendData,
byte sendLen, byte *backData = NULL,
byte *backLen = NULL, byte *validBits = NULL,
byte rxAlign = 0, bool checkCRC = false);
byte PICC_RequestA(byte *bufferATQA, byte *bufferSize);
byte PICC_WakeupA(byte *bufferATQA, byte *bufferSize);
byte PICC_REQA_or_WUPA(byte command, byte *bufferATQA, byte *bufferSize);
byte PICC_Select(Uid *uid, byte validBits = 0);
byte PICC_HaltA();
/////////////////////////////////////////////////////////////////////////////////////
// Functions for communicating with MIFARE PICCs
/////////////////////////////////////////////////////////////////////////////////////
byte PCD_Authenticate(byte command, byte blockAddr, MIFARE_Key *key,
Uid *uid);
void PCD_StopCrypto1();
byte MIFARE_Read(byte blockAddr, byte *buffer, byte *bufferSize);
byte MIFARE_Write(byte blockAddr, byte *buffer, byte bufferSize);
byte MIFARE_Decrement(byte blockAddr, long delta);
byte MIFARE_Increment(byte blockAddr, long delta);
byte MIFARE_Restore(byte blockAddr);
byte MIFARE_Transfer(byte blockAddr);
byte MIFARE_Ultralight_Write(byte page, byte *buffer, byte bufferSize);
byte MIFARE_GetValue(byte blockAddr, long *value);
byte MIFARE_SetValue(byte blockAddr, long value);
/////////////////////////////////////////////////////////////////////////////////////
// Support functions
/////////////////////////////////////////////////////////////////////////////////////
byte PCD_MIFARE_Transceive(byte *sendData, byte sendLen,
bool acceptTimeout = false);
// old function used too much memory, now name moved to flash; if you need
// char, copy from flash to memory
// const char *GetStatusCodeName(byte code);
const __FlashStringHelper *GetStatusCodeName(byte code);
byte PICC_GetType(byte sak);
// old function used too much memory, now name moved to flash; if you need
// char, copy from flash to memory
// const char *PICC_GetTypeName(byte type);
const __FlashStringHelper *PICC_GetTypeName(byte type);
void PICC_DumpToSerial(Uid *uid);
void PICC_DumpMifareClassicToSerial(Uid *uid, byte piccType,
MIFARE_Key *key);
void PICC_DumpMifareClassicSectorToSerial(Uid *uid, MIFARE_Key *key,
byte sector);
void PICC_DumpMifareUltralightToSerial();
void MIFARE_SetAccessBits(byte *accessBitBuffer, byte g0, byte g1, byte g2,
byte g3);
bool MIFARE_OpenUidBackdoor(bool logErrors);
bool MIFARE_SetUid(byte *newUid, byte uidSize, bool logErrors);
bool MIFARE_UnbrickUidSector(bool logErrors);
/////////////////////////////////////////////////////////////////////////////////////
// Convenience functions - does not add extra functionality
/////////////////////////////////////////////////////////////////////////////////////
bool PICC_IsNewCardPresent();
bool PICC_ReadCardSerial();
private:
byte _chipAddress;
byte _resetPowerDownPin; // Arduino pin connected to MFRC522's reset and
// power down input (Pin 6, NRSTPD, active low)
byte MIFARE_TwoStepHelper(byte command, byte blockAddr, long data);
};
#endif

25
lib/NFC/src/NfcReader.cpp Normal file
View File

@ -0,0 +1,25 @@
#include "NfcReader.h"
NfcReader::NfcReader(int i2c_adress)
{
this->mfrc522 = new MFRC522(i2c_adress);
this->mfrc522->PCD_Init();
}
String NfcReader::ReadNfc()
{
this->uid.clear();
if (!this->mfrc522->PICC_IsNewCardPresent() ||
!this->mfrc522->PICC_ReadCardSerial()) {
return ("0");
}
for (unsigned int i = 0; i < this->mfrc522->uid.size; i++) {
if (this->mfrc522->uid.uidByte[i] < 0xF) {
this->uid += '0';
this->uid += String(this->mfrc522->uid.uidByte[i], HEX);
} else {
this->uid += String(this->mfrc522->uid.uidByte[i], HEX);
}
}
return (this->uid);
}

21
lib/NFC/src/NfcReader.h Normal file
View File

@ -0,0 +1,21 @@
#ifndef NFCREADER_HPP_
#define NFCREADER_HPP_
#include <M5Stack.h>
#include "MFRC522_I2C.h"
#include <string>
class NfcReader {
public:
NfcReader(int i2c_adress);
~NfcReader() = default;
String ReadNfc();
protected:
private:
MFRC522 *mfrc522;
String uid;
};
#endif /* !NFCREADER_HPP_ */

View File

@ -0,0 +1,59 @@
#include "ServoMotorComponent.h"
/////////////////////////////////////////////////////////////////////////////////////
// Functions for setting up the ServoMotor
/////////////////////////////////////////////////////////////////////////////////////
/**
* Constructor.
* Prepares the ServoMotor.
*/
ServoMotorComponent::ServoMotorComponent(int PIN, unsigned long updatePeriod, float step) {
this->PIN = PIN;
this->myservo.attach(PIN);
this->desiredposition = Position::MIDDLE;
this->currentPosition = MIDDLE_POS;
this->lastUpTime = millis();
this->updatePeriod = updatePeriod;
this->step = step;
this->myservo.write(this->PIN, this->currentPosition);
}
/**
* Set the desired position
* @desiredPosition: Give desired position
*/
void ServoMotorComponent::setDesiredPosition(Position desiredPosition) {
switch (desiredPosition) {
case Position::LEFT:
this->desiredposition = LEFT_POS;
break;
case Position::MIDDLE:
this->desiredposition = MIDDLE_POS;
break;
case Position::RIGHT:
this->desiredposition = RIGHT_POS;
break;
default:
break;
}
}
/**
* Write a new servoMotor position when it's necessary
*/
void ServoMotorComponent::refresh() {
if (this->desiredposition == this->currentPosition
|| millis() - this->lastUpTime <= this->updatePeriod) return;
if (this->currentPosition > this->desiredposition) {
this->currentPosition -= this->step;
}
if (this->currentPosition < this->desiredposition) {
this->currentPosition += this->step;
}
this->lastUpTime = millis();
this->myservo.write(this->PIN, this->currentPosition);
}

View File

@ -0,0 +1,33 @@
#ifndef SERVOMOTOT_COMPONENT_H
#define SERVOMOTOT_COMPONENT_H
#include <Servo.h>
enum Position {
LEFT,
MIDDLE,
RIGHT
};
class ServoMotorComponent
{
public:
ServoMotorComponent(int PIN, unsigned long updatePeriod, float step = 1);
void setDesiredPosition(Position desiredPosition);
void refresh();
private:
int PIN;
float currentPosition;
float desiredposition;
Servo myservo;
unsigned long lastUpTime;
unsigned long updatePeriod;
float step;
};
#endif //SERVOMOTOT_COMPONENT_H

View File

@ -17,13 +17,14 @@ extra_configs =
secrets.ini
config.ini
envs.ini
config_api.ini
; Cache folder
build_cache_dir = ./.pio/cache
[env]
; build Envs
build_flags = ${config.build_flags} ${secrets.build_flags}
build_flags = ${config.build_flags} ${secrets.build_flags} ${config_api.build_flags}
; Add scripts for more functionnalities
; see individual scripts for more informations
@ -31,7 +32,7 @@ extra_scripts = pre:scripts/get_additionnal_envs.py
; Device Settings (make sure to fix versions where possible!)
platform = espressif32@4.2.0
board = esp32dev
board = m5stack-core-esp32
framework = arduino
; Monitoring settings
@ -50,6 +51,11 @@ upload_speed = 921600
; librairies (make sure to fix versions where possible!)
lib_deps =
bblanchon/ArduinoJson@^6.21.3 ; JSON serializer et deserializer
m5stack/M5Stack@^0.4.5 ; M5 Lib
m5stack/M5GFX@^0.1.9 ; M5 Lib pour le LCD
m5stack/Module_GRBL_13.2@^0.0.3 ; M5 Lib pour Stepper (GRBL)
dlloydev/ESP32 ESP32S2 AnalogWrite ; Lib pour le Servo Motor
; example:
; erropix/ESP32 AnalogWrite@0.2

View File

@ -4,3 +4,8 @@
[secrets]
build_flags =
-D WIFI_SSID=\"test\"
-D WIFI_PASSWORD=\"abcd1234\"
-D DOLIBARR_API_TOKEN=\"monapitokendedolibarr\"
-D DOLIBARR_URL=\"http://0.0.0.0/api/index.php\"
-D DEBUG=true

View File

@ -1,10 +1,33 @@
#include "Program.h"
#include "Arduino.h"
#include "DolibarrClient.h"
#include "ServoMotorComponent.h"
int initialize_wifi(WifiConfig wifi) {
WiFiClass::mode(WIFI_STA); //Optional
WiFi.setSleep(false);
WiFi.begin(wifi.ssid, wifi.password);
Serial.print("Connecting ");
while(WiFiClass::status() != WL_CONNECTED){
delay(WAITING_WIFI_DELAY);
Serial.print(".");
}
Serial.println("Connected to the WiFi network");
return 0;
}
Program::Program() {
// Startup
Serial.begin(MONITOR_SPEED);
this->servo = new ServoMotorComponent(2, 1, 0.1);
//struct WifiConfig wifi_c = {WIFI_SSID, WIFI_PASSWORD};
//struct DolibarrConfig dolibarr = {DOLIBARR_URL, DOLIBARR_API_TOKEN};
//initialize_wifi(wifi_c);
//this->client = new DolibarrClient(dolibarr);
}
void Program::loop() {
// Loop
this->servo->refresh();
this->servo->setDesiredPosition(Position::LEFT);
}

View File

@ -1,5 +1,4 @@
#include "Program.h"
Program* program;
void setup() {

10
test/dolibarr.cpp Normal file
View File

@ -0,0 +1,10 @@
#include <unity.h>
#include "DolibarrClient.h"
void test_construct_dolibarr_client() {
return;
}
void test_destroy_basic_state() {
return;
}

36
test/test.cpp Normal file
View File

@ -0,0 +1,36 @@
#include <M5Stack.h>
#include <unity.h>
#include "test.h"
void setUp(void) {
// set stuff up here
}
void tearDown(void) {
// clean stuff up here
}
int runUnityTests(void) {
UNITY_BEGIN();
RUN_TEST(test_construct_dolibarr_client);
return UNITY_END();
}
int main(void) {
return runUnityTests();
}
// For Arduino framework
void setup() {
// Wait ~2 seconds before the Unity test runner
// establishes connection with a board Serial interface
runUnityTests();
}
// For Arduino framework
void loop() {}
// For ESP-IDF framework
void app_main() {
runUnityTests();
}

6
test/test.h Normal file
View File

@ -0,0 +1,6 @@
#ifndef T_IOT_901_CONVOYOR_TEST_H
#define T_IOT_901_CONVOYOR_TEST_H
void test_construct_dolibarr_client();
#endif //T_IOT_901_CONVOYOR_TEST_H