test release v1

This commit is contained in:
2020-09-22 11:58:21 +02:00
commit 70a4b8a7db
22 changed files with 1154 additions and 0 deletions

5
.gitignore vendored Normal file
View File

@@ -0,0 +1,5 @@
.pio
.vscode/.browse.c_cpp.db*
.vscode/c_cpp_properties.json
.vscode/launch.json
.vscode/ipch

67
.travis.yml Normal file
View File

@@ -0,0 +1,67 @@
# Continuous Integration (CI) is the practice, in software
# engineering, of merging all developer working copies with a shared mainline
# several times a day < https://docs.platformio.org/page/ci/index.html >
#
# Documentation:
#
# * Travis CI Embedded Builds with PlatformIO
# < https://docs.travis-ci.com/user/integration/platformio/ >
#
# * PlatformIO integration with Travis CI
# < https://docs.platformio.org/page/ci/travis.html >
#
# * User Guide for `platformio ci` command
# < https://docs.platformio.org/page/userguide/cmd_ci.html >
#
#
# Please choose one of the following templates (proposed below) and uncomment
# it (remove "# " before each line) or use own configuration according to the
# Travis CI documentation (see above).
#
#
# Template #1: General project. Test it using existing `platformio.ini`.
#
# language: python
# python:
# - "2.7"
#
# sudo: false
# cache:
# directories:
# - "~/.platformio"
#
# install:
# - pip install -U platformio
# - platformio update
#
# script:
# - platformio run
#
# Template #2: The project is intended to be used as a library with examples.
#
# language: python
# python:
# - "2.7"
#
# sudo: false
# cache:
# directories:
# - "~/.platformio"
#
# env:
# - PLATFORMIO_CI_SRC=path/to/test/file.c
# - PLATFORMIO_CI_SRC=examples/file.ino
# - PLATFORMIO_CI_SRC=path/to/test/directory
#
# install:
# - pip install -U platformio
# - platformio update
#
# script:
# - platformio ci --lib="." --board=ID_1 --board=ID_2 --board=ID_N

7
.vscode/extensions.json vendored Normal file
View File

@@ -0,0 +1,7 @@
{
// See http://go.microsoft.com/fwlink/?LinkId=827846
// for the documentation about the extensions.json format
"recommendations": [
"platformio.platformio-ide"
]
}

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

@@ -0,0 +1,39 @@
{
"files.associations": {
"functional": "cpp",
"array": "cpp",
"atomic": "cpp",
"*.tcc": "cpp",
"cctype": "cpp",
"clocale": "cpp",
"cmath": "cpp",
"cstdarg": "cpp",
"cstdint": "cpp",
"cstdio": "cpp",
"cstdlib": "cpp",
"cwchar": "cpp",
"cwctype": "cpp",
"deque": "cpp",
"list": "cpp",
"unordered_map": "cpp",
"vector": "cpp",
"exception": "cpp",
"fstream": "cpp",
"initializer_list": "cpp",
"iosfwd": "cpp",
"istream": "cpp",
"limits": "cpp",
"new": "cpp",
"ostream": "cpp",
"numeric": "cpp",
"sstream": "cpp",
"stdexcept": "cpp",
"streambuf": "cpp",
"cinttypes": "cpp",
"tuple": "cpp",
"type_traits": "cpp",
"utility": "cpp",
"typeinfo": "cpp",
"string": "cpp"
}
}

7
data/src/bootstrap.min.css vendored Normal file

File diff suppressed because one or more lines are too long

7
data/src/bootstrap.min.js vendored Normal file

File diff suppressed because one or more lines are too long

79
data/src/index.html Normal file
View File

@@ -0,0 +1,79 @@
<!doctype html>
<html lang="en">
<head> <!-- Required meta tags -->
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<link rel="stylesheet" href="/src/bootstrap.min.css">
<title>BROT-O-MAT 8000</title>
<style>
html, body {
overflow-x: hidden;
}
body {
position: relative;
}
</style>
<meta content='width=device-width; initial-scale=1.0; maximum-scale=1.0; user-scalable=0;' name='viewport' />
<meta name="viewport" content="width=device-width" />
<meta name="apple-mobile-web-app-capable" content="yes">
<meta name="apple-mobile-web-app-title" content="BROT-O-MAT">
<meta name="apple-mobile-web-app-status-bar-style" content="black">
<link rel="apple-touch-icon" href="/src/logo.png">
</head>
<body>
<div class="jumbotron">
<h1 class="display-4">BROT-O-MAT</h1>
<p class="lead">Die ultimative Brot-Drehmaschine</p>
</div>
<div class="container">
<div class="card" style="width: *;">
<div class="card-body">
<h5 class="card-title">Akku</h5>
<div class="progress">
<div class="progress-bar" id="akku_bar" role="progressbar" style="width: 25%;" aria-valuenow="25" aria-valuemin="0" aria-valuemax="100">25%</div>
</div>
<p style="display: inline-block;"><b>Spannung: </b></p><p style="display: inline-block;" id="volts">0.00V</p><br>
<p style="display: inline-block;"><b>Geschwindigkeit: </b></p><p style="display: inline-block;" id="rots">0.00 U/Min</p>
</div>
</div>
</div>
<br />
<div class="container">
<div class="card" style="width: *;">
<div class="card-body">
<h5 class="card-title">Drehrichtung</h5>
<div class="btn-group" role="group" aria-label="Basic example" style="width: *;display: flex;">
<a class="btn btn-outline-success" id="cmd_back" style="flex: 1;">Links</a>
<a class="btn btn-danger" id="cmd_stop" style="flex: 1;">Stop</a>
<a class="btn btn-outline-success" id="cmd_forward" style="flex: 1;">Rechts</a><br>
</div>
</div>
</div>
<br />
<div class="card" style="width: *;">
<div class="card-body">
<h5 class="card-title">Geschwindigkeit</h5>
<div class="btn-group" role="group" aria-label="Basic example" style="width: *;display: flex;">
<a class="btn btn-secondary" id="cmd_s1" style="flex: 1;">1</a>
<a class="btn btn-secondary" id="cmd_s2" style="flex: 1;">2</a>
<a class="btn btn-secondary" id="cmd_s3" style="flex: 1;">3</a>
<a class="btn btn-secondary" id="cmd_s4" style="flex: 1;">4</a>
<a class="btn btn-secondary" id="cmd_s5" style="flex: 1;">5</a>
<a class="btn btn-secondary" id="cmd_s6" style="flex: 1;">6</a>
<a class="btn btn-secondary" id="cmd_s7" style="flex: 1;">7</a>
<a class="btn btn-secondary" id="cmd_s8" style="flex: 1;">8</a>
<a class="btn btn-secondary" id="cmd_s9" style="flex: 1;">9</a>
<a class="btn btn-secondary" id="cmd_s10" style="flex: 1;">10</a>
</div>
</div>
</div>
<!-- Optional JavaScript --> <!-- jQuery first, then Popper.js, then Bootstrap JS -->
<script src="/src/jquery-3.5.1.slim.min.js"></script>
<script src="/src/popper.min.js"></script>
<script src="/src/bootstrap.min.js"></script>
<script src="/src/index.js"></script>
</body>
</html>

104
data/src/index.js Normal file
View File

@@ -0,0 +1,104 @@
let dir = 1;
let speed = 1;
let rev = 0;
let volts = 0.00;
let perc = 100.00;
$(document).ready(function(){
$( "#cmd_back" ).click(() => setDir(0));
$( "#cmd_stop" ).click(() =>setDir(1));
$( "#cmd_forward" ).click(() =>setDir(2));
$( "#cmd_s1" ).click(() =>setSpeed(1));
$( "#cmd_s2" ).click(() =>setSpeed(2));
$( "#cmd_s3" ).click(() =>setSpeed(3));
$( "#cmd_s4" ).click(() =>setSpeed(4));
$( "#cmd_s5" ).click(() =>setSpeed(5));
$( "#cmd_s6" ).click(() =>setSpeed(6));
$( "#cmd_s7" ).click(() =>setSpeed(7));
$( "#cmd_s8" ).click(() =>setSpeed(8));
$( "#cmd_s9" ).click(() =>setSpeed(9));
$( "#cmd_s10" ).click(() =>setSpeed(10));
reloadData();
setInterval(() => reloadData(),500);
});
function setSpeed(speed){
$.ajax({
type: "POST",
url: "/setSpeed",
data: `${speed}`,
contentType: 'text/plain',
success: function(){
reloadData();
},
})
}
function setDir(dir){
$.ajax({
type: "POST",
url: "/setDir",
data: `${dir}`,
contentType: 'text/plain',
success: function(){
reloadData();
},
})
}
function reloadData(){
$.ajax({
type: "GET",
url: "/getStatus",
success: function(data){
console.log(data)
speed = data.speed;
dir = data.dir;
rev = data.rev;
volts = data.volts || 0;
perc = data.perc || 100;
updateSpeed();
updateDir();
updateText();
},
})
}
function updateSpeed(){
let active_name = `cmd_s${speed}`;
let all = ['cmd_s1','cmd_s2','cmd_s3','cmd_s4','cmd_s5','cmd_s6','cmd_s7','cmd_s8','cmd_s9','cmd_s10'].filter(el => el != active_name);
all.forEach(el => {
$(`#${el}`).addClass("btn-outline-secondary").removeClass("btn-secondary");
})
$(`#${active_name}`).addClass("btn-secondary").removeClass("btn-outline-secondary")
}
function updateDir(){
switch(dir){
case 0:
$(`#cmd_back`).addClass("btn-success").removeClass("btn-outline-success")
$(`#cmd_stop`).addClass("btn-outline-danger").removeClass("btn-danger")
$(`#cmd_forward`).addClass("btn-outline-success").removeClass("btn-success")
break;
case 1:
$(`#cmd_back`).addClass("btn-outline-success").removeClass("btn-success")
$(`#cmd_stop`).addClass("btn-danger").removeClass("btn-outline-danger")
$(`#cmd_forward`).addClass("btn-outline-success").removeClass("btn-success")
break;
case 2:
$(`#cmd_back`).addClass("btn-outline-success").removeClass("btn-success")
$(`#cmd_stop`).addClass("btn-outline-danger").removeClass("btn-danger")
$(`#cmd_forward`).addClass("btn-success").removeClass("btn-outline-success")
break;
}
}
function updateText(){
$(`#rots`).text(` ${rev} U/min`)
$(`#volts`).text(` ${volts} V`)
}

BIN
data/src/jquery-3.5.1.slim.min.js vendored Normal file

Binary file not shown.

BIN
data/src/logo.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 46 KiB

5
data/src/popper.min.js vendored Normal file

File diff suppressed because one or more lines are too long

39
include/README Normal file
View File

@@ -0,0 +1,39 @@
This directory is intended for project header files.
A header file is a file containing C declarations and macro definitions
to be shared between several project source files. You request the use of a
header file in your project source file (C, C++, etc) located in `src` folder
by including it, with the C preprocessing directive `#include'.
```src/main.c
#include "header.h"
int main (void)
{
...
}
```
Including a header file produces the same results as copying the header file
into each source file that needs it. Such copying would be time-consuming
and error-prone. With a header file, the related declarations appear
in only one place. If they need to be changed, they can be changed in one
place, and programs that include the header file will automatically use the
new version when next recompiled. The header file eliminates the labor of
finding and changing all the copies as well as the risk that a failure to
find one copy will result in inconsistencies within a program.
In C, the usual convention is to give header files names that end with `.h'.
It is most portable to use only letters, digits, dashes, and underscores in
header file names, and at most one dot.
Read more about using header files in official GCC documentation:
* Include Syntax
* Include Operation
* Once-Only Headers
* Computed Includes
https://gcc.gnu.org/onlinedocs/cpp/Header-Files.html

46
lib/README Normal file
View File

@@ -0,0 +1,46 @@
This directory is intended for project specific (private) libraries.
PlatformIO will compile them to static libraries and link into executable file.
The source code of each library should be placed in a an own separate directory
("lib/your_library_name/[here are source files]").
For example, see a structure of the following two libraries `Foo` and `Bar`:
|--lib
| |
| |--Bar
| | |--docs
| | |--examples
| | |--src
| | |- Bar.c
| | |- Bar.h
| | |- library.json (optional, custom build options, etc) https://docs.platformio.org/page/librarymanager/config.html
| |
| |--Foo
| | |- Foo.c
| | |- Foo.h
| |
| |- README --> THIS FILE
|
|- platformio.ini
|--src
|- main.c
and a contents of `src/main.c`:
```
#include <Foo.h>
#include <Bar.h>
int main (void)
{
...
}
```
PlatformIO Library Dependency Finder will find automatically dependent
libraries scanning project source files.
More information about PlatformIO Library Dependency Finder
- https://docs.platformio.org/page/librarymanager/ldf.html

18
platformio.ini Normal file
View File

@@ -0,0 +1,18 @@
; PlatformIO Project Configuration File
;
; Build options: build flags, source filter
; Upload options: custom upload port, speed and extra flags
; Library options: dependencies, extra library storages
; Advanced options: extra scripting
;
; Please visit documentation for the other options and examples
; https://docs.platformio.org/page/projectconf.html
[env:nodemcuv2]
platform = espressif8266
board = nodemcuv2
framework = arduino
monitor_speed = 115200
upload_port = COM9

0
src/bootstrap.h Normal file
View File

211
src/io.cpp Normal file
View File

@@ -0,0 +1,211 @@
#include <Wire.h>
#include <Arduino.h>
#include "io.hpp"
#include "motion.hpp"
char pa = 0x00;
char pb = 0x00;
uint32_t dly_1 = 0;
uint32_t dly_2 = 0;
uint32_t dly_3 = 0;
uint32_t dly_4 = 0;
byte inputs_last = 0;
extern struct Motion motion;
void updateLamps(){
if (motion.direction == 1){
setLamp(1,0);
setLamp(2,2);
setLamp(3,0);
}else if (motion.direction == 2){
setLamp(2,0);
setLamp(3,0);
setLamp(1, (motion.speed == 10) + 1);
}else if (motion.direction == 0){
setLamp(1,0);
setLamp(2,0);
setLamp(3, (motion.speed == 10) + 1);
}
}
ICACHE_RAM_ATTR void panelPress() {
noInterrupts();
//Serial.println("BUTTON DETECTED!!!");
Wire.beginTransmission(0x20);
Wire.write(0x13); // set MCP23017 memory pointer to GPIOB address
Wire.endTransmission();
Wire.requestFrom(0x20, 1); // request one byte of data from MCP20317
byte inputs = Wire.read();
delay(20); // for debounce
//change
if (inputs_last != inputs){
byte changes = inputs^inputs_last;
inputs_last = inputs;
if ((changes & 0x02) > 0){
Serial.println("Button 1");
if (motion.direction == 1){
motion.direction = 0;
changeDir();
} else if (motion.direction == 0){
if ((inputs & 0x02) > 0 && motion.speed < 10){
motion.speed++;
changeSpeed();
}
} else if (motion.direction == 2){
if ((inputs & 0x02) > 0 && motion.speed > 1){
motion.speed--;
changeSpeed();
}
}
}
if ((changes & 0x04) > 0){
Serial.println("Button 2");
motion.direction = 1;
changeDir();
}
if ((changes & 0x08) > 0){
Serial.println("Button 3");
if (motion.direction == 1){
motion.direction = 2;
changeDir();
} else if (motion.direction == 0){
if ((inputs & 0x08) > 0 && motion.speed > 1){
motion.speed--;
changeSpeed();
}
} else if (motion.direction == 2){
if ((inputs & 0x08) > 0 && motion.speed < 10){
motion.speed++;
changeSpeed();
}
}
}
if ((changes & 0x10) > 0){
Serial.println("Button 4");
}
}
interrupts();
}
void sendI2Cmessage(char msg[], int bytes){
Wire.beginTransmission(addr_controller1);
for (int i = 0; i<bytes; i++){
Wire.write(msg[i]);
}
Wire.endTransmission();
}
void setupI2C(){
Wire.begin(pin_sda,pin_scl);
//test if connected
Wire.beginTransmission(addr_controller1);
int error = Wire.endTransmission();
if (error != 0)
{
Serial.println("IO Controller not found!");
ESP.reset();
}
//setup registers
char mcp_io_a[] = {MCP23017_IODIRA,0x00};
sendI2Cmessage(mcp_io_a,2);
char mcp_io_b[] = {MCP23017_IODIRB,0b00011110};
sendI2Cmessage(mcp_io_b,2);
char mcp_gppu_a[] = {MCP23017_GPPUA,0xFF};
sendI2Cmessage(mcp_gppu_a,2);
char mcp_gppu_b[] = {MCP23017_GPPUB,0b00011110};
sendI2Cmessage(mcp_gppu_b,2);
//enable interrupt for front panel buttons
char mcp_ipol_b[] = {MCP23017_IPOLB,0b00011110};
sendI2Cmessage(mcp_ipol_b,2);
char mcp_gpinten_b[] = {MCP23017_GPINTENB,0b00011110};
sendI2Cmessage(mcp_gpinten_b,2);
char mcp_iocon[] = {MCP23017_IOCONB ,0b00000010};
sendI2Cmessage(mcp_iocon,2);
//set motor speed
char mot[] = {LCD_MOTOR,0xFF,0x00};
sendI2Cmessage(mot,3);
pb |= pb_m_en;
updateOut();
for(int i =0; i < 4; i++){
lampmodes[i] = 0;
lampstate[i] = 0;
lamplast[i] = 0;
}
attachInterrupt(digitalPinToInterrupt(14), panelPress, CHANGE);
panelPress();
}
void updateOut(){
char mcp_gpio_a[] = {0x12,pb};
sendI2Cmessage(mcp_gpio_a,2);
char mcp_gpio_b[] = {0x13,pa};
sendI2Cmessage(mcp_gpio_b,2);
//Serial.println(String(mcp_gpio_a[0], BIN));
Serial.println(String(pb, BIN));
}
void setLamp(int id, int mode){
lampmodes[id] = mode;
lampstate[id] = (mode == 1 || mode == 2);
if (mode == 1){
lamplast[id] == millis();
}
outLamp(id,lampstate[id]);
char mcp_gpio_a[] = {0x12,pb};
sendI2Cmessage(mcp_gpio_a,2);
}
void updateIO(){
bool changed = false;
for(int i =0; i < 4; i++){
if (lampmodes[i] == 1 && (lamplast[i] + lamp_blink) < millis()){
lampstate[i] = (~lampstate[i]) & 0x01;
outLamp(i,lampstate[i]);
changed = true;
lamplast[i] = millis();
}
}
if(changed){
char mcp_gpio_a[] = {0x12,pb};
sendI2Cmessage(mcp_gpio_a,2);
}
}
void outLamp(int id, int val){
if (val == 1){
pb |= (1<<(id+4));
}else{
pb &= ~(1<<(id+4));
}
}
void sendDisplay(byte addr, byte data){
Wire.beginTransmission(0x08);
Wire.write(addr);
Wire.write(data);
Wire.endTransmission();
}
void setMotorTimer(uint16_t value){
char mot[] = {LCD_MOTOR,(uint8_t)value & 0xff ,(uint8_t)(value >> 8) };
Wire.beginTransmission(0x08);
for (int i = 0; i<3; i++){
Wire.write(mot[i]);
}
Wire.endTransmission();
}

81
src/io.hpp Normal file
View File

@@ -0,0 +1,81 @@
#define addr_controller1 0x20
#define MCP23017_IODIRA 0x00 //!< I/O direction register A
#define MCP23017_IPOLA 0x02 //!< Input polarity port register A
#define MCP23017_GPINTENA 0x04 //!< Interrupt-on-change pins A
#define MCP23017_DEFVALA 0x06 //!< Default value register A
#define MCP23017_INTCONA 0x08 //!< Interrupt-on-change control register A
#define MCP23017_IOCONA 0x0A //!< I/O expander configuration register A
#define MCP23017_GPPUA 0x0C //!< GPIO pull-up resistor register A
#define MCP23017_INTFA 0x0E //!< Interrupt flag register A
#define MCP23017_INTCAPA 0x10 //!< Interrupt captured value for port register A
#define MCP23017_GPIOA 0x12 //!< General purpose I/O port register A
#define MCP23017_OLATA 0x14 //!< Output latch register 0 A
#define MCP23017_IODIRB 0x01 //!< I/O direction register B
#define MCP23017_IPOLB 0x03 //!< Input polarity port register B
#define MCP23017_GPINTENB 0x05 //!< Interrupt-on-change pins B
#define MCP23017_DEFVALB 0x07 //!< Default value register B
#define MCP23017_INTCONB 0x09 //!< Interrupt-on-change control register B
#define MCP23017_IOCONB 0x0B //!< I/O expander configuration register B
#define MCP23017_GPPUB 0x0D //!< GPIO pull-up resistor register B
#define MCP23017_INTFB 0x0F //!< Interrupt flag register B
#define MCP23017_INTCAPB 0x11 //!< Interrupt captured value for port register B
#define MCP23017_GPIOB 0x13 //!< General purpose I/O port register B
#define MCP23017_OLATB 0x15 //!< Output latch register 0 B
#define LCD_BATBAL 0x01
#define LCD_BATPERC 0x02
#define LCD_ROTS 0x03
#define LCD_SPEED 0x04
#define LCD_DIRECTION 0x05
#define LCD_MOTOR 0x06
#define pin_sda 4
#define pin_scl 5
//pin definitions
// PORTA
#define pa_dir 0x00
#define pa_m_s3 0x01 //active low
#define pa_sw_stop 0x02
#define pa_sw_reset 0x04
#define pa_sw_forward 0x08
#define pa_sw_backward 0x10
#define pa_res1 0x20
#define pa_res2 0x40
#define pa_res3 0x80
#define pb_dir 0b00011110
#define pb_led_stop 0x80
#define pb_led_reset 0x40
#define pb_led_forward 0x20
#define pb_led_backward 0x10
#define pb_m_dir 0x08
#define pb_m_en 0x04
#define pb_m_s0 0x02
#define pb_m_s1 0x01
#define lamp_blink 500
#define lmpode_off 0x02
#define lmpode_blink 0x01
#define lmpode_on 0x00
static int lampmodes[4];
static int lampstate[4];
static uint32_t lamplast[4];
void setLamp(int id, int mode);
void setupI2C();
void sendI2Cmessage(char msg[], int bytes);
void updateOut();
void outLamp(int id, int val);
void updateIO();
void updateLamps();
void sendDisplay(byte addr, byte data);
void setMotorTimer(uint16_t value);

142
src/main.cpp Normal file
View File

@@ -0,0 +1,142 @@
#include <Arduino.h>
#include <ESP8266WiFi.h>
#include <WiFiClient.h>
#include <FS.h>
#include <ESPAsyncWebServer.h>
#include "motion.hpp"
#include <string>
#include "io.hpp"
const char *ssid = "Brot";
const char *pw = "12345678";
const double volt_mul = 15.75;
extern char pa;
extern char pb;
uint32_t t_bat = 0;
double volts = 0;
AsyncWebServer server(80); //Server on port 80
Motion motion;
void measureBatteryLevel(){
if((t_bat + 2000) < millis()){
t_bat = millis();
int sensorValue = analogRead(A0);
volts = ((double)sensorValue / 1023) * volt_mul * 3.3;
}
}
//===============================================================
// SETUP
//===============================================================
void setup(void){
Serial.begin(115200);
pinMode(A0,INPUT);
setupI2C();
setupDriver();
setLamp(0,0);
updateLamps();
changeSpeed();
changeDir();
Serial.println("");
if(!SPIFFS.begin()){
Serial.println("An Error has occurred while mounting SPIFFS");
return;
}
WiFi.mode(WIFI_AP); //Only Access point
WiFi.softAP(ssid, pw); //Start HOTspot removing password will disable security
IPAddress myIP = WiFi.softAPIP(); //Get IP address
Serial.print("HotSpt IP:");
Serial.println(myIP);
//server.on("/", handleRoot); //Which routine to handle at root location
server.on("/", HTTP_GET, [](AsyncWebServerRequest *request){
request->send(SPIFFS, "/src/index.html", "text/html");
});
server.on("/getStatus", HTTP_GET, [](AsyncWebServerRequest *request){
String speed = String(motion.speed);
String direction = String(motion.direction);
char copy[50];
String full = "{\"speed\":" + speed + ",\"dir\":"+ direction + ",\"rev\":"+ String(motion.lastspeed) + ",\"volts\":"+ String(volts) + "}";
full.toCharArray(copy,50);
request->send(200,"text/json",copy);
});
server.on("/setSpeed", HTTP_POST, [](AsyncWebServerRequest * request){}, NULL, [](AsyncWebServerRequest * request, uint8_t *data, size_t len, size_t index, size_t total) {
String body = "";
for (size_t i = 0; i < len; i++) {body += char(data[i]);}
int speed = body.toInt();
if (speed > 0 && speed < 11){
motion.speed = speed;
request->send(200);
}else{
request->send(400);
}
changeSpeed();
});
server.on("/setDir", HTTP_POST, [](AsyncWebServerRequest * request){}, NULL, [](AsyncWebServerRequest * request, uint8_t *data, size_t len, size_t index, size_t total) {
String body = "";
for (size_t i = 0; i < len; i++) {body += char(data[i]);}
int direction = body.toInt();
if (direction >= 0 && direction < 3){
motion.direction = direction;
request->send(200);
}else{
request->send(400);
}
changeDir();
});
//static libs
server.on("/src/bootstrap.min.css",HTTP_GET, [](AsyncWebServerRequest *request){
request->send(SPIFFS, "/src/bootstrap.min.css", "text/css");
});
server.on("/src/bootstrap.min.js", HTTP_GET, [](AsyncWebServerRequest *request){
request->send(SPIFFS, "/src/bootstrap.min.js", "text/javascript");
});
server.on("/src/jquery-3.5.1.slim.min.js", HTTP_GET, [](AsyncWebServerRequest *request){
request->send(SPIFFS, "/src/jquery-3.5.1.slim.min.js", "text/javascript");
});
server.on("/src/popper.min.js", HTTP_GET, [](AsyncWebServerRequest *request){
request->send(SPIFFS, "/src/popper.min.js", "text/javascript");
});
server.on("/src/index.js", HTTP_GET, [](AsyncWebServerRequest *request){
request->send(SPIFFS, "/src/index.js", "text/javascript");
});
server.on("/src/logo.png", HTTP_GET, [](AsyncWebServerRequest *request){
request->send(SPIFFS, "/src/logo.png", "image/png");
});
server.begin(); //Start server
Serial.println("HTTP server started");
}
//===============================================================
// LOOP
//===============================================================
void loop(void){
updateDriver();
measureBatteryLevel();
updateIO();
}

72
src/main.cpp_working Normal file
View File

@@ -0,0 +1,72 @@
#include <Arduino.h>
#include <ESP8266WiFi.h>
#include <WiFiClient.h>
#include <ESP8266WebServer.h>
#include <FS.h>
const char *ssid = "Brot";
const char *pw = "12345678";
ESP8266WebServer server(80); //Server on port 80
//==============================================================
// This rutine is exicuted when you open its IP in browser
//==============================================================
void handleRoot() {
server.send(200, "text/plain", "hello from esp8266!");
}
//===============================================================
// SETUP
//===============================================================
void setup(void){
Serial.begin(115200);
Serial.println("");
if(!SPIFFS.begin()){
Serial.println("An Error has occurred while mounting SPIFFS");
return;
}
WiFi.mode(WIFI_AP); //Only Access point
WiFi.softAP(ssid, pw); //Start HOTspot removing password will disable security
IPAddress myIP = WiFi.softAPIP(); //Get IP address
Serial.print("HotSpt IP:");
Serial.println(myIP);
//server.on("/", handleRoot); //Which routine to handle at root location
server.on("/", HTTP_GET, [](){
File f = SPIFFS.open("/src/index.html","r");
server.send(200,"text/html",f.readString());
});
//static libs
server.on("/src/bootstrap.min.css", HTTP_GET, [](){
File f = SPIFFS.open("/src/bootstrap.min.css","r");
server.send(200,"text/css",f.readString());
});
server.on("/src/bootstrap.min.js", HTTP_GET, [](){
File f = SPIFFS.open("/src/bootstrap.min.js","r");
server.send(200,"text/javascript",f.readString());
});
server.on("/src/jquery-3.5.1.slim.min.js", HTTP_GET, [](){
File f = SPIFFS.open("/src/jquery-3.5.1.slim.min.js","r");
server.send(200,"text/javascript",f.readString());
});
server.on("/src/popper.min.js", HTTP_GET, [](){
File f = SPIFFS.open("/src/popper.min.js","r");
server.send(200,"text/css",f.readString());
});
server.begin(); //Start server
Serial.println("HTTP server started");
}
//===============================================================
// LOOP
//===============================================================
void loop(void){
server.handleClient(); //Handle client requests
}

185
src/motion.cpp Normal file
View File

@@ -0,0 +1,185 @@
#include <Arduino.h>
#include <motion.hpp>
#include "io.hpp"
extern struct Motion motion;
extern char pa;
extern char pb;
uint32_t lastSpeedCalc = 0;
long double vc = 0; //v current
long double vl = 0; //v current
long double vt = 0; //v target
long double vo = 0; //v origin
double a = 0;
double a_max = 20;
double dir = 1;
int phase = 10;
int lastState = 0; // 0: off //1: on
void setupDriver() {
pinMode(pin_Step, OUTPUT); //Step pin as output
digitalWrite(pin_Step, LOW); // Currently no stepper motor movement
pb |= pb_m_en | pb_m_s0;
pb &= ~(pb_m_dir | pb_m_s1);
pa &= ~(pa_m_s3);
updateOut();
updateOut();
t_last = 0;
t_draw = 0;
t_delay = 10;
motion.speed = 5;
motion.direction = 1;
motion.steps = 0;
motion.lastspeed = 0.0;
}
void tstep(){
digitalWrite(pin_Step, HIGH);
delayMicroseconds(5);
digitalWrite(pin_Step, LOW);
}
double getTrigger(){
double sr = ((double)a_max / accel);
double t_vt = vt;
double t_a = a_max;
for (int i = 0; i < accel; i++) {
t_a -= sr;
t_vt -= t_a;
}
if (dir == -1) {
t_vt = (vt - t_vt) + vt;
}
return t_vt;
}
void calcMaxAccel() {
double v_target =((vt - vc) / 2.2);
//bekannt dauer
a_max = fabs(v_target / accel);
}
void updateDriver(){
if(motion.direction == 1){
vt = 0;
}else{
vt = motion.speed * 20;
}
if ((lastSpeedCalc + accl_dly) < millis()){
lastSpeedCalc = millis();
//calculate acceleration
if (phase == 0) {
double sr = ((double)a_max / accel); //inc per step
a += sr;
if (a >= a_max) {
phase = 1;
}
vc += a * dir;
}
else if (phase == 1) {
//constant
vc += a * dir;
if (vc >= getTrigger() && dir == 1) {
phase = 2;
} else if (vc <= getTrigger() && dir == -1) {
phase = 2;
}
}
else if (phase == 2) {
double sr = ((double)a_max / accel); //inc per step
a -= sr;
vc += a * dir;
if (a <= 0) {
//stop
phase = 10;
vc = vt;
//end stop
}
if (dir == 1 && vc > vt) {
vc = vt;
phase = 10;
}
else if(dir == -1 && vc < vt) {
vc = vt;
phase = 10;
}
}
else if(phase == 10){
if (vc != vt){
calcMaxAccel();
vo = vc;
phase = 0;
if (vc < vt) {
dir = 1;
}
else {
dir = -1;
}
}
}
}
if (vc > 200){
vc = 200;
}else if (vc < 0){
vc = 0;
}
if(lastState == 0 && vc > 0){
lastState = 1 ;
pb &= ~(pb_m_en);
updateOut();
}else if(lastState == 1 && vc == 0){
lastState = 0 ;
pb |= pb_m_en;
updateOut();
}else{
if (vc != vl && vc != 0){
vl = vc;
double ad = (1/vc);
uint16_t tempSpd = ad*4000;
Serial.print("ad: ");
Serial.println(ad);
Serial.print("tempSpd: ");
Serial.println(tempSpd);
setMotorTimer(tempSpd);
}
}
if (t_sec + 1000 < millis()){
t_sec = millis();
double rev_pre_min = ((double)(motion.steps) / steps_per_rev)*60;
motion.lastspeed = rev_pre_min;
motion.steps = 0;
sendDisplay(LCD_SPEED,(motion.speed) & 0xFF);
sendDisplay(LCD_ROTS,(int)((double)motion.lastspeed * (double)10) & 0xFF);
}
}
void changeDir(){
switch(motion.direction){
case 0:
pb |= pb_m_dir;
break;
case 1:
break;
case 2:
pb &= ~( pb_m_dir);
break;
}
updateLamps();
updateOut();
sendDisplay(LCD_DIRECTION,(motion.direction) & 0xFF);
}
void changeSpeed(){
updateLamps();
}

29
src/motion.hpp Normal file
View File

@@ -0,0 +1,29 @@
#define pin_Step 0 //GPIO0---D3 of Nodemcu--Step of stepper motor driver
#define steps_per_rev 2566
#define accel 20
#define accl_dly 20
enum MotionDirection { backward, stop, forward };
static uint32_t t_last;
static uint32_t t_draw;
static uint32_t t_delay;
static uint32_t t_sec;
struct Motion {
int direction;
int speed;
int steps;
double lastspeed;
};
void setupDriver();
void updateDriver();
void tstep();
void changeDir();
void changeSpeed();

11
test/README Normal file
View File

@@ -0,0 +1,11 @@
This directory is intended for PIO Unit Testing and project tests.
Unit Testing is a software testing method by which individual units of
source code, sets of one or more MCU program modules together with associated
control data, usage procedures, and operating procedures, are tested to
determine whether they are fit for use. Unit testing finds problems early
in the development cycle.
More information about PIO Unit Testing:
- https://docs.platformio.org/page/plus/unit-testing.html