Hendrik Langer
7 years ago
12 changed files with 377 additions and 2 deletions
@ -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 */ |
@ -0,0 +1,9 @@ |
|||||
|
#include "led.h" |
||||
|
|
||||
|
using namespace std; |
||||
|
|
||||
|
Led::Led(void) { |
||||
|
} |
||||
|
|
||||
|
void Led::setup(void) { |
||||
|
} |
@ -0,0 +1,11 @@ |
|||||
|
#ifndef _LED_H |
||||
|
#define _LED_H |
||||
|
|
||||
|
class Led { |
||||
|
public: |
||||
|
Led(void); |
||||
|
void setup(void); |
||||
|
private: |
||||
|
}; |
||||
|
|
||||
|
#endif /* _LED_H */ |
@ -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; |
||||
|
} |
||||
|
} |
@ -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 */ |
@ -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); |
||||
|
} |
@ -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 */ |
@ -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; |
||||
|
} |
@ -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…
Reference in new issue