Skip to main content

ESP32 - Complex Waveform Generator V2

Setting Up The App

Modify ESP C+ Code to configure local network settings
    1. Determine your local network's Subnet range (It should be one of these: 10.0.0.0/8, 192.168.0.0/16, or 172.xxx.xxx.xxx) 
      1. See: https://www.businessinsider.com/how-to-find-ip-address-of-router
      2. Write down the address of your Gateway (your Router's IP address)
    2. Find a free DHCP issued internal IP address on your local network (Guess an IP not in use by picking a number between 100 and 255 for the very last position in your subnet: 192.168.1.xxx)
    3. Find your WIFI SSID and Password
      1. SSID = The name of your Wifi Connection as your Phone or PC would see it on the network connection browser
      2. Password = Your Wifi Password
    4. Configure the IP, Gateway and your Wifi SSID & credentials into the ESP code below
      1. Preview Of areas to change in code below:

        // #### Change Me ####
        const char *SSID = "NETGEAR";
        const char *PWD = "12345678";
        
        // Don't Change Me
        const char *ASSET_HOST = "https://wavegenjs.s3.amazonaws.com";
        
        // Web server running on port 80
        WebServer server(80);
        
        // #### CHANGE ME ####
        // Set your Static IP address
        IPAddress local_IP(192, 168, 1, 8);
        // Set your Gateway IP address
        IPAddress gateway(192, 168, 1, 1);
        
    5. Copy the full script (down below) and paste it into your Arduino IDE
      1. See: https://randomnerdtutorials.com/how-to-install-esp8266-board-arduino-ide/
    6. Compile and Upload the code to the ESP32
      1. Install required libraries (FreeRTOS, ArduinoJSON, Wifi, and WebServer.) 
        1. See: https://docs.arduino.cc/software/ide-v1/tutorials/installing-libraries
        2. 298171574_5523327307690078_4273704313364637631_n.jpg
        3. 298253535_5523321941023948_4638314484689292979_n.jpg
      2. Observe the Serial Monitor Log output from the Arduino IDE
      3. Confirm network connectivity was established with your router.
    7. Connect 2 separate Oscilloscope probes to pins "0" and "2" to ground, on your ESP.
    8. Open a web browser on a computer connected to the same internal network as the ESP was given
      1. Go to the ESP's given IP Address: http://192.168.1.8
    9. Enjoy! (if it works)
Troubleshooting:

View the Console Log for errors in your browser while clicking the app's sliders buttons etc..

Screenshot from 2022-08-06 13-24-55.png

https://www.browserstack.com/guide/inspect-element-in-chrome#:~:text=One%20of%20the%20easiest%20ways,%2C%20Sources%2C%20and%20other%20tools.

Confirm the ESP is a connected host in your network and was given the IP you specified

https://www.wikihow.com/See-Who-Is-Connected-to-Your-Wireless-Network


ESP C+ Code

Expand
#include <Arduino.h>
#include <WiFi.h>
#include <WebServer.h>
#include <ArduinoJson.h>
#include <FreeRTOS.h>

TaskHandle_t pulseTaskHandle;

// #### Change Me ####
const char *SSID = "NETGEAR";
const char *PWD = "12345678";

// Don't Change Me
//const char *ASSET_HOST = "https://wavegenjs.s3.amazonaws.com";
const char *ASSET_HOST = "http://192.168.1.2";

// Web server running on port 80
WebServer server(80);

// #### CHANGE ME ####
// Set your Static IP addres
IPAddress local_IP(192, 168, 1, 8);
// Set your Gateway IP address
IPAddress gateway(192, 168, 1, 1);

IPAddress subnet(255, 255, 255, 0);
IPAddress primaryDNS(8, 8, 8, 8);   //optional
IPAddress secondaryDNS(8, 8, 4, 4); //optional

// JSON data buffer
StaticJsonDocument<500> jsonDocument;
char buffer[500];

// env variable
float width = 150;
float space = 150;
float width1 = 0;
float space1 = 0;
float widthelongationmodifier = 1;
float spaceelongationmodifier = 1;
float gate = 1;
int count = 5;
int enablegate = 1;
int channels = 2;
int reference1 = LOW;
int reference2 = HIGH;
int enablealternate = 0;
int invertOne = 0;
int invertTwo = 0;
int ch1lastState = LOW;
int ch2lastState = LOW;

void connectToWiFi() {
  Serial.print("Connecting to ");
  Serial.println(SSID);
  // Configures static IP address
  if (!WiFi.config(local_IP, gateway, subnet, primaryDNS, secondaryDNS)) {
    Serial.println("STA Failed to configure");
  }
  WiFi.begin(SSID, PWD);
  while (WiFi.status() != WL_CONNECTED) {
    Serial.print(".");
    delay(500);
  }
  Serial.print("Connected. IP: ");
  Serial.println(WiFi.localIP());
}

void setup_routing() {
  server.enableCORS();
  server.on("/metrics", getMetrics);
  server.on("/set", HTTP_POST, handlePost);
  server.on("/", getIndex);
  server.begin();
}

void create_json(float width, float space, float count, float gate, float enablegate, float channels, float widthelongationmodifier, float spaceelongationmodifier, float enablealternate, int invertOne, int invertTwo) {
  jsonDocument.clear();
  jsonDocument["width"] = width;
  jsonDocument["space"] = space;
  jsonDocument["widthelongationmodifier"] = widthelongationmodifier;
  jsonDocument["spaceelongationmodifier"] = spaceelongationmodifier;
  jsonDocument["count"] = count;
  jsonDocument["gate"] = gate;
  jsonDocument["enablegate"] = enablegate;
  jsonDocument["channels"] = channels;
  jsonDocument["enablealternate"] = enablealternate;
  jsonDocument["invertOne"] = invertOne;
  jsonDocument["invertTwo"] = invertTwo;
  serializeJson(jsonDocument, buffer);
}

String getHtml() {
  String ptr = "<!DOCTYPE html> <html>\n";
  ptr +="<head><meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0, user-scalable=no\">\n";
  ptr +="<title>ESP32 Complex Waveform Generator</title>\n";
  ptr +="<script src=\"https://code.jquery.com/jquery-3.6.0.min.js\" integrity=\"sha256-/xUj+3OJU5yExlq6GSYGSHk7tPXikynS7ogEvDej/m4=\" crossorigin=\"anonymous\"></script>";
  ptr +="<link href=\"https://cdn.jsdelivr.net/npm/bootstrap@5.2.0/dist/css/bootstrap.min.css\" rel=\"stylesheet\" crossorigin=\"anonymous\"><script src=\"https://cdn.jsdelivr.net/npm/bootstrap@5.2.0/dist/js/bootstrap.bundle.min.js\" crossorigin=\"anonymous\"></script>";
  ptr +="<script src=\"https://code.highcharts.com/highcharts.js\"></script>";
  
  ptr +="<link href=\"";
  ptr += ASSET_HOST;
  ptr += "/espwavegen.css\" rel=\"stylesheet\"><script src=\"";
  ptr += ASSET_HOST;
  ptr += "/espwavegen.js\"></script>";
  ptr +="</head><body><div id=\"mainBody\"></div><div id=\"pulseChart\"></div><div id=\"widthChart\"></div></body></html>\n";
  return ptr;
}

void getIndex() {
  server.send(200, "text/html", getHtml()); 
}

void getMetrics() {
  create_json(width, space, count, gate, enablegate, channels, widthelongationmodifier, spaceelongationmodifier, enablealternate, invertOne, invertTwo);
  server.send(200, "application/json", buffer);
}

void handlePost() {
  if (server.hasArg("plain") == false) {
      Serial.println("no plain mode");
  }
  String body = server.arg("plain");
  deserializeJson(jsonDocument, body);
  width = jsonDocument["widthtotal"];
  space = jsonDocument["spacetotal"];
  widthelongationmodifier = jsonDocument["widthelongationmodifier"];
  spaceelongationmodifier = jsonDocument["spaceelongationmodifier"];
  count = jsonDocument["count"];
  gate = jsonDocument["gatetotal"];
  enablegate = jsonDocument["enablegate"];
  channels = jsonDocument["channels"];
  invertOne = jsonDocument["invertOne"];
  invertTwo = jsonDocument["invertTwo"];
  enablealternate = jsonDocument["enablealternate"];
  
  serializeJson(jsonDocument, buffer);
  server.send(200, "application/json", buffer);
}

void customDelay(long delayValue)
{
  long i = 0;
  int x = 0;
  for(i=0;i<delayValue;i++){
    for(x=0;x<80;x++){
      __asm__("nop\n\t");
    }
  }
}

void pulseClock(void * parameter) {
  Serial.println("restart loop");
  for(;;){ // ** Start of infinite loop **
     if(invertOne) {
      if(ch1lastState == LOW){
        ch1lastState = HIGH;
      } else {
        ch1lastState = LOW;
      }
    }
    if(invertTwo) {
      if(ch2lastState == LOW){
        ch2lastState = HIGH;
      } else {
        ch2lastState = LOW;
      }
    }
   
   width1 = width;
   space1 = space;
   for(int i=0; i<count; i++){    
      digitalWrite(2, ch2lastState);
      digitalWrite(0, ch1lastState);
      customDelay(width1);
//      ch1lastState = !ch1lastState;
//      ch2lastState = !ch2lastState;
      digitalWrite(2, !ch2lastState);
      digitalWrite(0, !ch1lastState);
      customDelay(space1);
      digitalWrite(2, ch2lastState);
      digitalWrite(0, ch1lastState);
      width1 = width1 * widthelongationmodifier;
      space1 = space1 * spaceelongationmodifier;
    }

    
    if(enablegate){
      if(enablealternate) {
        if(reference1 == HIGH){
          reference1 = LOW;
          reference2 = HIGH;
        } else {
          reference1 = HIGH;
          reference2 = LOW;
        }
    
        digitalWrite(2, reference1);
        digitalWrite(0, reference2);
      }      
      customDelay(gate);
    }
  }
  vTaskDelete(NULL);
}

void setup() {
  Serial.begin(115200);
  Serial.println("setup");
  connectToWiFi();
  setup_routing();

  pinMode(2, OUTPUT);
  pinMode(0, OUTPUT);
  pinMode(19, OUTPUT);
  pinMode(21, OUTPUT);
  digitalWrite(2, LOW);
  digitalWrite(0, LOW);
  digitalWrite(19, LOW);
  digitalWrite(21, LOW);

  xTaskCreatePinnedToCore(pulseClock,"Pulse Clock",10000,NULL,1,&pulseTaskHandle,1); 
}

void loop() {
  server.handleClient();
}