Browse Source

initial esp32 software

main
Hendrik Langer 6 years ago
parent
commit
3df5c2149a
  1. 7
      README.md
  2. 11
      software/platformio.ini
  3. 11
      software/src/hardware.h
  4. 9
      software/src/led.cpp
  5. 11
      software/src/led.h
  6. 14
      software/src/main.cpp
  7. 46
      software/src/pusher.cpp
  8. 26
      software/src/pusher.h
  9. 142
      software/src/webserver.cpp
  10. 16
      software/src/webserver.h
  11. 65
      software/src/wifi.cpp
  12. 21
      software/src/wifi.h

7
README.md

@ -19,6 +19,13 @@ Hints:
* Align the elements so that the outer shell lines match the sliding direction
* the stl files are not (yet) correctly aligned for printing. please rotate
## Software
* mkspiffs -c [src_folder] -b 4096 -p 256 -s 0x100000 spiffs.bin
* python esptool.py --chip esp32 --port [port] --baud [baud] write_flash -z 0x110000 spiffs.bin
* platformio run
* platformio run --target upload
* platformio device monitor -b 115200
## Contributing
Feel free to remix this design and/or send pull requests to me.

11
software/platformio.ini

@ -9,6 +9,15 @@
; http://docs.platformio.org/page/projectconf.html
[env:esp32dev]
platform = espressif32_stage
;platform = https://github.com/platformio/platform-espressif32.git#feature/stage
platform = espressif32
board = esp32dev
framework = arduino
lib_deps =
https://github.com/me-no-dev/ESPAsyncWebServer.git
https://github.com/me-no-dev/AsyncTCP.git
; ESP Async WebServer
; AsyncTCP
FS
FastLED
lib_ignore = ESPAsyncTCP

11
software/src/hardware.h

@ -0,0 +1,11 @@
#ifndef _HARDWARE_H
#define _HARDWARE_H
#define WIFI_SSID "ssid"
#define WIFI_PASSWORD "password"
#define LED_BUILTIN 13
static constexpr int SERVO_PINS[] = {22, 23, 24, 25};
#endif /* _HARDWARE_H */

9
software/src/led.cpp

@ -0,0 +1,9 @@
#include "led.h"
using namespace std;
Led::Led(void) {
}
void Led::setup(void) {
}

11
software/src/led.h

@ -0,0 +1,11 @@
#ifndef _LED_H
#define _LED_H
class Led {
public:
Led(void);
void setup(void);
private:
};
#endif /* _LED_H */

14
software/src/main.cpp

@ -6,14 +6,26 @@
#include <Arduino.h>
#define LED_BUILTIN 13
#include "hardware.h"
#include "wifi.h"
#include "webserver.h"
#include "pusher.h"
Wifi wifi;
Webserver webserver;
Pusher pusher;
void setup()
{
Serial.begin(112500);
Serial.println("Hello");
// initialize LED digital pin as an output.
pinMode(LED_BUILTIN, OUTPUT);
wifi.connect();
webserver.start();
pusher.setup();
}
void loop()

46
software/src/pusher.cpp

@ -0,0 +1,46 @@
#include <Arduino.h>
#include "esp32-hal-ledc.h"
#include "semaphore.h"
#include "hardware.h"
#include "pusher.h"
using namespace std;
Pusher::Pusher(void) {
xSemaphore = xSemaphoreCreateMutex();
}
void Pusher::setup(void) {
int channel = 1;
int pin = 22;
for(auto pin : SERVO_PINS) {
if (xSemaphoreTake(xSemaphore, TIMEOUT) == pdTRUE) {
ledcSetup(channel, 50, TIMER_WIDTH);
ledcAttachPin(pin, channel);
ledcWrite(channel, MAX_PULSE_WIDTH);
ledcDetachPin(pin);
xSemaphoreGive(xSemaphore);
}
}
}
void Pusher::dispense(int num) {
if (xSemaphoreTake(xSemaphore, TIMEOUT) == pdTRUE) {
int channel = 1;
int pin = SERVO_PINS[num];
if (channel >= LEDC_NUM_CHANNELS) {
return;
}
ledcSetup(channel, 50, TIMER_WIDTH);
ledcAttachPin(pin, channel);
ledcWrite(channel, MIN_PULSE_WIDTH);
delay(1000);
ledcWrite(channel, MAX_PULSE_WIDTH);
delay(1000);
xSemaphoreGive(xSemaphore);
} else {
return;
}
}

26
software/src/pusher.h

@ -0,0 +1,26 @@
#ifndef _PUSHER_H
#define _PUSHER_H
#include <cstdint>
#include "semaphore.h"
static constexpr uint16_t MIN_PULSE_WIDTH = 544; // the shortest pulse sent to a servo
static constexpr uint16_t MAX_PULSE_WIDTH = 2400; // the longest pulse sent to a servo
static constexpr uint16_t DEFAULT_PULSE_WIDTH = 1500; // default pulse width
static constexpr uint8_t LEDC_NUM_CHANNELS = 8; // default pulse width
static constexpr TickType_t TIMEOUT = portMAX_DELAY;
#define TIMER_WIDTH 16
class Pusher {
public:
Pusher(void);
void setup(void);
void dispense(int);
private:
volatile SemaphoreHandle_t xSemaphore;
};
#endif /* _PUSHER_H */

142
software/src/webserver.cpp

@ -0,0 +1,142 @@
#include <WiFi.h>
#include <ESPmDNS.h>
#include <AsyncTCP.h>
#include <ESPAsyncWebServer.h>
#include "webserver.h"
using namespace std;
Webserver::Webserver(void)
: server(80) {
}
String processor(const String& var)
{
if(var == "HELLO_FROM_TEMPLATE")
return F("Hello world!");
if(var == "FACH0_NAME")
return F("Hello world!");
if(var == "FACH1_NAME")
return F("Hello world!");
if(var == "FACH2_NAME")
return F("Hello world!");
return String();
}
const char index_html[] PROGMEM =
"<html><head><title>Vending Machine</title></head>"
"<body><h1>Vending Machine</h1>"
"<table><tr><td>%FACH0_NAME%</td><td>%FACH1_NAME%</td><td>%FACH2_NAME%</td></tr>"
"<tr><td></td><td></td><td></td></tr></table>"
"</body></html>"; // large char array, tested with 14k
void Webserver::start(void) {
startMDNS();
// respond to GET requests on URL /heap
server.on("/heap", HTTP_GET, [](AsyncWebServerRequest *request){
request->send(200, "text/plain", String(ESP.getFreeHeap()));
});
//First request will return 0 results unless you start scan from somewhere else (loop/setup)
//Do not request more often than 3-5 seconds
server.on("/scan", HTTP_GET, [](AsyncWebServerRequest *request){
String json = "[";
int n = WiFi.scanComplete();
if(n == -2){
WiFi.scanNetworks(true);
} else if(n){
for (int i = 0; i < n; ++i){
if(i) json += ",";
json += "{";
json += "\"rssi\":"+String(WiFi.RSSI(i));
json += ",\"ssid\":\""+WiFi.SSID(i)+"\"";
json += ",\"bssid\":\""+WiFi.BSSIDstr(i)+"\"";
json += ",\"channel\":"+String(WiFi.channel(i));
json += ",\"secure\":"+String(WiFi.encryptionType(i));
// json += ",\"hidden\":"+String(WiFi.isHidden(i)?"true":"false");
json += "}";
}
WiFi.scanDelete();
if(WiFi.scanComplete() == -2){
WiFi.scanNetworks(true);
}
}
json += "]";
request->send(200, "text/json", json);
json = String();
});
server.on("/", HTTP_GET, [](AsyncWebServerRequest *request){
request->send_P(200, "text/html", index_html, processor);
});
server.onNotFound([](AsyncWebServerRequest *request){
Serial.printf("NOT_FOUND: ");
if(request->method() == HTTP_GET)
Serial.printf("GET");
else if(request->method() == HTTP_POST)
Serial.printf("POST");
else if(request->method() == HTTP_DELETE)
Serial.printf("DELETE");
else if(request->method() == HTTP_PUT)
Serial.printf("PUT");
else if(request->method() == HTTP_PATCH)
Serial.printf("PATCH");
else if(request->method() == HTTP_HEAD)
Serial.printf("HEAD");
else if(request->method() == HTTP_OPTIONS)
Serial.printf("OPTIONS");
else
Serial.printf("UNKNOWN");
Serial.printf(" http://%s%s\n", request->host().c_str(), request->url().c_str());
if(request->contentLength()){
Serial.printf("_CONTENT_TYPE: %s\n", request->contentType().c_str());
Serial.printf("_CONTENT_LENGTH: %u\n", request->contentLength());
}
int headers = request->headers();
int i;
for(i=0;i<headers;i++){
AsyncWebHeader* h = request->getHeader(i);
Serial.printf("_HEADER[%s]: %s\n", h->name().c_str(), h->value().c_str());
}
int params = request->params();
for(i=0;i<params;i++){
AsyncWebParameter* p = request->getParam(i);
if(p->isFile()){
Serial.printf("_FILE[%s]: %s, size: %u\n", p->name().c_str(), p->value().c_str(), p->size());
} else if(p->isPost()){
Serial.printf("_POST[%s]: %s\n", p->name().c_str(), p->value().c_str());
} else {
Serial.printf("_GET[%s]: %s\n", p->name().c_str(), p->value().c_str());
}
}
request->send(404);
});
server.begin();
Serial.println("Webserver started.");
}
void Webserver::startMDNS(void) {
// Set up mDNS responder:
// - first argument is the domain name, in this example
// the fully-qualified domain name is "esp8266.local"
// - second argument is the IP address to advertise
// we send our IP address on the WiFi network
if (!MDNS.begin("esp32")) {
Serial.println("Error setting up MDNS responder!");
while(1) {
delay(1000);
}
}
Serial.println("mDNS responder started");
// Add service to MDNS-SD
MDNS.addService("http", "tcp", 80);
}

16
software/src/webserver.h

@ -0,0 +1,16 @@
#ifndef _WEBSERVER_H
#define _WEBSERVER_H
#include <AsyncTCP.h>
#include <ESPAsyncWebServer.h>
class Webserver {
public:
Webserver(void);
void start(void);
private:
void startMDNS(void);
AsyncWebServer server;
};
#endif /* _WEBSERVER_H */

65
software/src/wifi.cpp

@ -0,0 +1,65 @@
#include <WiFi.h>
#include <WiFiMulti.h>
#include <Preferences.h>
#include "hardware.h"
#include "wifi.h"
using namespace std;
Wifi::Wifi() {}
void Wifi::reconnectTask(void* parameters) {
while(true) {
if(wifiMulti.run() != WL_CONNECTED) {
Serial.println("WiFi not connected!");
}
vTaskDelay(3000 / portTICK_PERIOD_MS);
}
Serial.println("WiFi disconnecting!");
WiFi.disconnect();
vTaskDelete(NULL);
}
void Wifi::cTaskWrapper(void* parameters) {
static_cast<Wifi*>(parameters)->reconnectTask(NULL);
}
void Wifi::connect() {
wifiMulti.addAP(WIFI_SSID, WIFI_PASSWORD);
Serial.println("Connecting to WiFi network");
if(wifiMulti.run() == WL_CONNECTED) {
Serial.println("");
Serial.println("WiFi connected");
Serial.println("IP address: ");
Serial.println(WiFi.localIP());
}
xTaskCreate(
&cTaskWrapper, /* Task function. */
"wifiReconnectTask", /* String with name of task. */
1024, /* Stack size in words. */
this, /* Parameter passed as input of the task */
1, /* Priority of the task. */
&wifiTaskHandle); /* Task handle. */
}
void Wifi::disconnect() {
}
size_t Wifi::getStoredPassword(const char* ssid, char* value) {
Preferences preferences;
preferences.begin("wifi-pwd", false);
size_t len = preferences.getString(ssid, value, 64);
preferences.end();
return len;
}
size_t Wifi::setStoredPassword(const char* ssid, char* value) {
Preferences preferences;
preferences.begin("wifi-pwd", false);
size_t len = preferences.putString(ssid, value);
preferences.end();
return len;
}

21
software/src/wifi.h

@ -0,0 +1,21 @@
#ifndef _WIFI_H
#define _WIFI_H
#include <WiFi.h>
#include <WiFiMulti.h>
class Wifi {
public:
Wifi();
void connect();
void disconnect();
private:
void reconnectTask(void*);
static void cTaskWrapper(void*);
WiFiMulti wifiMulti;
TaskHandle_t wifiTaskHandle;
size_t getStoredPassword(const char* ssid, char* value);
size_t setStoredPassword(const char* ssid, char* value);
};
#endif /* _WIFI_H */
Loading…
Cancel
Save