tomsim
tomsim
Reputation Top 1%
Tom Sim
IoT newbie on esp8266 arduino
11 Snippets  (76th place)
Published
3 Channels
Created
5 Channels
Following
Apr 19, 2018
Last Visit
Aug 15, 2016
Registered
1488 points  (36th place)
Reputation
Junior Code Generator
Serious Code Generator
Junior Publisher
Serious Publisher
Junior Topic Hub
Junior Trend Maker
Junior Popular Coder
Junior Autobiographer
Serious Autobiographer
Master Autobiographer
Junior Snip2Coder
Serious Famous Coder
Senior Famous Coder
Junior Wise Coder

Recent Snippets See all snippets by tomsim

public by tomsim created Jan 21, 2018  1468  2  6  0

Simple RPC call

Simple function to call RPC (only 1k uncompressed). Use this instead of JQuery. Alternatively, use zepto.min.js from zeptojs.com if you have 26K to spare.
/* 
Addapted from Paolo Manna git pmanna/mongoose_os_playground browser_rpc_service.js
*/

var platform = '';
var host = '';

var defCallBack = function(response) {
  if ((response) && (response.error)) {
	  alert(response.message);
  }
};

// Common call to RPC services on the board
function callRPCService(cmd, params, callback) {
  if (!callback) {
	  callback = defCallBack;
  }
  var xhttp = new XMLHttpRequest();
  
  xhttp.onreadystatechange = function() {
    if (this.readyState == 4 && this.status == 200) {
      callback(this.response);
    }
  };
  
  xhttp.open('POST', 'rpc/' + cmd + '?' + new Date().getTime(), true);
  xhttp.responseType = 'json';
  xhttp.send(JSON.stringify(params));
}

// Discover which platform we're using, to enable/disable features
function startup() {
  callRPCService('Config.Get',{}, function(response) {
    if (response) {
      platform = response.device.id;
      console.log('Platform is: ' + platform);

      var mac_id = (response.device.id.split("_"))[1];

      host = mac_id + '.local';
      document.getElementById("hostname").innerHTML = host;
    }
  });
}

// Reboots the microcontroller
function rebootDevice() {
  callRPCService('Sys.Reboot',{delay_ms:500});
}

						
;

public by tomsim created Jan 21, 2018  1452  1  5  0

Using simple RPC service

Use simple rpc script to call RPC service on small IOT devices
<html>
<head>
	<script src="simple_rpc_service.js"></script>
</head>
<body onLoad='startup();'>
<h4 id="hostname"> </h4>
<p>Hello, see <a target="_blank" href="/rpc/Config.Get">rpc</a>
<br><a target="_blank" href="/rpc/clearAll">clear strip</a>

<p><table>
  <tr><td>Pin</td> <td><input type="number" id="GPIO.pin" value='2'/></td></tr>
  <tr><td>Red</td><td><input type="range" id="rval" name="rval" min="0" max="255" value='0' onchange="setPixel()"/></td></tr>
  <tr><td>Green</td><td><input type="range" id="gval" name="gval" min="0" max="255" value='0' onchange="setPixel()"/></td></tr>
  <tr><td>Blue</td><td><input type="range" id="bval" name="bval" min="0" max="255" value='0' onchange="setPixel()"/></td></tr>
</table>
<p><button href="#" id="setPixel" onclick="setPixel()">Set Pixel</button>
<button href="#" id="clearAll" onclick="callRPCService('clearAll')">Clear All Pixel</button>
<p><button href="#" id="setPixel" onclick="rebootDevice()">Reboot</button>

<script>

  var log = function(msg) {
    console.log(msg);
  };
  log('Starting ...');
  function setPixel() {
    log("setPixel...");
  	var pin = parseInt(document.getElementById("GPIO.pin").value);
  	var rv = parseInt(document.getElementById("rval").value);
  	var gv = parseInt(document.getElementById("gval").value);
  	var bv = parseInt(document.getElementById("bval").value);
	callRPCService('setPixel',{px:pin, r:rv, g:gv, b:bv});
  };
</script>

</body>
</html>
;

public by tomsim created Jan 21, 2018  1341  3  6  0

ESP8266 wifi web server setup

Lambda style Wifi web server with DHT22 data upload to ThingSpeak
/* DHTServer - ESP8266 Webserver with a DHT sensor as an input

   Based on ESP8266Webserver, DHTexample, and BlinkWithoutDelay (thank you)

   Version 1.0  5/3/2014  Version 1.0 Mike Barela for Adafruit Industries
*/
#include <ESP8266WiFi.h>
#include <WiFiClient.h>
#include <ESP8266WebServer.h>
#include <DHT.h>
#include <TimeLib.h>
#include "ThingSpeak.h"

#define DHTTYPE DHT22

const int DHTPIN = D4;

const char* ssid     = "mySSID";
const char* password = "myPassword";

ESP8266WebServer server(80);

/*============ ThingSpeak setup ==================*/
// Note:  Each channel has its own number and write API key
// API key is what get used - wrong channel number doesn't matter

// Temperature Humidity Channel
static unsigned long myChannelNumber = 123456;
static const char 	*myWriteAPIKey = "AB1CDEF6HIJKLMNO";
static WiFiClient  client;

/*============ End ThingSpeak setup ==============*/


// Initialize DHT sensor 
// NOTE: For working with a faster than ATmega328p 16 MHz Arduino chip, like an ESP8266,
// you need to increase the threshold for cycle counts considered a 1 or 0.
// You can do this by passing a 3rd parameter for this threshold.  It's a bit
// of fiddling to find the right value, but in general the faster the CPU the
// higher the value.  The default for a 16mhz AVR is a value of 6.  For an
// Arduino Due that runs at 84mhz a value of 30 works.
// This is for the ESP8266 processor on ESP-01 
DHT dht(DHTPIN, DHTTYPE, 11); // 11 works fine for ESP8266
 
float lastHumdty, lastTempF;  // Values read from sensor
static int nextSampleMinute = 15;
static int minuteSampleInterval = 15;

// Generally, you should use "unsigned long" for variables that hold time
unsigned long previousMillis = 0;        // will store last temp was read
const long interval = 2000;              // interval at which to read sensor

void getTemperature() {
  // Wait at least 2 seconds seconds between measurements.
  // if the difference between the current time and last time you read
  // the sensor is bigger than the interval you set, read the sensor
  // Works better than delay for things happening elsewhere also
  unsigned long currentMillis = millis();
 
  if(currentMillis - previousMillis >= interval) {
    // save the last time you read the sensor 
    previousMillis = currentMillis;   

    // Reading temperature for humidity takes about 250 milliseconds!
    // Sensor readings may also be up to 2 seconds 'old' (it's a very slow sensor)
    lastHumdty = dht.readHumidity();          // Read humidity (percent)
    lastTempF = dht.readTemperature(true);     // Read temperature as Fahrenheit
    // Check if any reads failed and exit early (to try again).
    if (isnan(lastHumdty) || isnan(lastTempF)) {
      Serial.println("Failed to read from DHT sensor!");
      return;
    }
  }
}

static int uploadData(void)
{
	ThingSpeak.setField( 1, lastTempF);
	ThingSpeak.setField( 2, lastHumdty);
	int rc = ThingSpeak.writeFields(myChannelNumber, myWriteAPIKey);
//	Serial.println(String("Post rc=")+rc);
	return rc;
}

 
const String HTML_TYPE = "text/html";

void handle_null() {
    Serial.println("Handle null");
	server.send(200,HTML_TYPE,"");
	delay(100);
}
void handleRoot()
{
	String wstr = 
	"<p>Hello from the weather esp8266, read from /temp or /humidity"
	"<br>set <a href=/set?minuteSampleInterval=5>5 minute</a> sample interval"
	", <a href=/set?nextSampleMinute=15>sample at 15 </a> minute"
	"<br>Take <a href=/sample>sample Data</a> and upload to ThingSpeak"
	"<br><a href=/temp>Get Temperature</a>"
	"<br><a href=/humidity>Get Humidity</a>";
	wstr += "<br>Last temperature: " + String(lastTempF)+"F";
	wstr += " humidity: " + String(lastHumdty)+"%";
	wstr += "<br>Current minute: " + String(minute(now()));
	wstr += " next sample time: " + String(nextSampleMinute)+" min.";
	wstr += " sample interval: " + String(minuteSampleInterval)+" min.";
	server.send(200,HTML_TYPE, wstr);
	delay(100);
}
void doSample()
{
	Serial.println("DoSample");
	getTemperature();
	int rc = uploadData();
	String wstr = "<p>Take sample data:  ";
	wstr += "<br>Temperature " + String(lastTempF);
	wstr += "<br>Humidity " + String(lastHumdty);
	wstr += "<br>Upload thingspeak rc=" + String(rc);
	server.send(200,HTML_TYPE, wstr);
}
 
// Web Server Service Definition structure
// =======================================
typedef struct s_WebServiceDef
{
	const char *urlName;
	void (*doit)(void);
} WebServiceDef;

/* =======================================================================
	Define web service definition here
	Each entry has a URL name and a lambda function to service the request
   =======================================================================
*/
static WebServiceDef wsd[] = {
	{ "/", handleRoot },
	{ "/favicon", handle_null },
	{ "/temp",			// url name
		[] ()				// lambda function
		{
			getTemperature();       // read sensor
			String wstr="Temperature: "+String((int)lastTempF)+" F";
			server.send(200, "text/plain", wstr);   // send to someones browser when asked
		}
	},
	{ "/humidity", []()
		{ 
			getTemperature();
			String wstr="Humidity: "+String((int)lastHumdty)+"%";
			server.send(200, "text/plain", wstr);
		}
	},
	{ "/sample", doSample },
	{ "/set", []()
		{
			String n = String("minuteSampleInterval");
			if (server.hasArg(n))
			{
				int v = server.arg(n).toInt();
				if (v)
					minuteSampleInterval = v;
			}
			n = String("nextSampleMinute");
			if (server.hasArg(n))
			{
				int v = server.arg(n).toInt();
				if (v)
					nextSampleMinute = v;
			}
			server.send(200, "text/plain", "ok");
		}
	},
 	{0,0}
};

static void setupServerHandler(void)
{
	for (int i; wsd[i].urlName; i++)
	{
		server.on( wsd[i].urlName, wsd[i].doit);
	}
	server.onNotFound(handleRoot);
}

static int nextAlarmMin(int sampleInterval)
{
	int nextMin = minute(now());
	nextMin = ((nextMin + sampleInterval) % 60);	// alarm every 5 min
	return nextMin;
}



void setup(void)
{
	// You can open the Arduino IDE Serial Monitor window to see what the code is doing
	Serial.begin(115200);  // Serial connection from ESP-01 via 3.3v console cable
	dht.begin();           // initialize temperature sensor

	// Connect to WiFi network
	WiFi.begin(ssid, password);
	Serial.print("\n\r \n\rWorking to connect");

	// Wait for connection
	while (WiFi.status() != WL_CONNECTED) {
	delay(500);
	Serial.print(".");
	}
	Serial.println("");
	Serial.println("DHT Weather Reading Server");
	Serial.print("Connected to ");
	Serial.println(ssid);
	Serial.print("IP address: ");
	Serial.println(WiFi.localIP());

	ThingSpeak.begin(client);

	setupServerHandler();

	server.begin();
	Serial.println("HTTP server started");
}
 
void loop(void)
{
	int currentMinute = minute(now());

	if (currentMinute == nextSampleMinute)
	{
		// trigger sample at set interval
		Serial.println("Regular sample");
		getTemperature();
		int rc = uploadData();
		Serial.println("rc=" + String(rc));

		nextSampleMinute = nextAlarmMin(minuteSampleInterval);
		delay(1000);
	}

	server.handleClient();
} 

;

public by tomsim created Aug 27, 2016  2369  16  5  0

Send UDP WOL Magic Package

C program to send UDP magic package to wake on lan
/* Compile on Windows:
cl /nologo /W3 /O2 /D "NDEBUG" /D "WIN32" /D "_CONSOLE" /D "_X86_" /link wsock32.lib wol.c
Compile on linux:
gcc wol.c -o wol

Change the subnet on line 161 to match your network (sorry!)
Must configure nic to accept magic package and setup power profile to allow
wake on lan from nic.  Not for WiFi.
*/
#ifdef _WIN32
#define WIN32_LEAN_AND_MEAN
#include <winsock2.h>
#else
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>
#include <arpa/inet.h>
#endif

#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <errno.h>
#include <stdarg.h>
#include <string.h>

#ifdef _WIN32
#define ERR_RETURN( x, e) if (x == SOCKET_ERROR) { checkError( e); return(0); }
#else
#define ERR_RETURN( x, e) if (x < 0) { checkError( e); return(0); }
#define SOCKET int
#endif

static int checkError( char *szMsg)
{
#ifdef _WIN32
	int err = WSAGetLastError();
	if ((err == WSAEINTR) || (err == WSAEWOULDBLOCK) || (err == WSAEINPROGRESS))
	{
		printf( "Warning error=%08.8x\n", errno);
		return 1;
	}
	else
	{
		printf("Error %d: %s\n", err, szMsg);
		WSACleanup();
		return 0;
	}
#else
	perror(szMsg);
	if ((errno == EINTR) || (errno = EWOULDBLOCK) || (errno == EINPROGRESS))
		return 1;
	else
		return 0;
#endif
}
#ifdef _WIN32
/*--------------------------------------------------------
  Window socket startup
  --------------------------------------------------------*/
int socketStartWin32(void)
{
	WSADATA wsaData;
	if (WSAStartup(0x202,&wsaData) == SOCKET_ERROR)
	{
		printf("WSAStartup failed with error %d\n",WSAGetLastError());
		WSACleanup();
		return -1;
	}
	return 0;
}
void socketEndWin32(void)
{
   WSACleanup();
}
#endif

/* Magic package format:
	06 x 255 or (0xff)
	16 x MAC Address of target PC

*/ 
int main(int argc, char **argv)
{
	int i;
	unsigned char tosend[102];
	unsigned char mac[6];

	if ((argc < 2) || (strlen(argv[1]) < 17))
	{
		printf("Usage wol <mac address aa:bb:cc:dd:ee:ff>\n");
		exit(0);
	}

	/** store mac address **/
	for (i=0; i < sizeof(mac); i++)
	{
		char *cp = &argv[1][i*3];
		mac[i] = 0x00;
		sscanf(cp,"%2X", (unsigned int *) &mac[i]);
	}
	if (argc > 2)	// validate before sent
	{
		int ecn = 0;
		printf( "Send magic package to ");
		for (i=0; i < sizeof(mac); i++)
		{
			if (i) printf(":");
			printf( "%.2X", mac[i]);
			if (!mac[i]) ecn++;
		}
		printf("\n");
		if (ecn)
		{
			printf("Invalid mac address\n");
			exit(0);
		}
	}


	/** first 6 bytes of 255 **/
	for( i = 0; i < 6; i++) {
		tosend[i] = 0xFF;
	}
	/** append it 16 times to packet **/
	for( i = 1; i <= 16; i++)
	{
		memcpy(&tosend[i * 6], mac, 6 * sizeof(unsigned char));
	}

#ifdef _WIN32
	if (socketStartWin32())
		exit(-1);
#endif
	if (1)
	{
		int udpSocket;
		struct sockaddr_in udpClient, udpServer;
		int broadcast = 1;
		int rv;

		udpSocket = socket(AF_INET, SOCK_DGRAM, 0);

		/** you need to set this so you can broadcast **/
		if (setsockopt(udpSocket, SOL_SOCKET, SO_BROADCAST, (char *) &broadcast, sizeof broadcast))
		{
			checkError("setsockopt (SO_BROADCAST)");
			exit(1);
		}
		udpClient.sin_family = AF_INET;
		udpClient.sin_addr.s_addr = INADDR_ANY;
		udpClient.sin_port = 0;

		bind(udpSocket, (struct sockaddr*)&udpClient, sizeof(udpClient));

		/** …make the packet as shown above **/

		/** set server end point (the broadcast addres)**/
		udpServer.sin_family = AF_INET;
		udpServer.sin_addr.s_addr = inet_addr("192.168.1.255");
		udpServer.sin_port = htons(9);

		/** send the packet **/
		rv = sendto(udpSocket, tosend, sizeof(unsigned char) * sizeof(tosend), 0, (struct sockaddr*)&udpServer, sizeof(udpServer));
		if (argc > 2) printf( "Sent %d bytes\n", rv);
	}

#ifdef _WIN32
	socketEndWin32();
#endif
	return 0;
}

                                    
;

public by tomsim created Aug 20, 2016  2172  0  5  0

Rotary Encoder State table

Read Rotary Encoder using state table instead of interrupt
/* Common 2 pins rotary encoder (ignore push button pin)
  Default pin output = (0,0)
  Read each pin and combine them into one value
  then use it to index the state table to advance to next state
  State sequence 00->01->11->10->00 return -1
      Next state  0   1   3   2   0
                 00->10->11->01->00 return +1
                  0   2   3   1   0
*/
const int ENC_A = 2;
const int ENC_B = 3;

// State table
static uint8_t stb[][4] =
{
//       0 1 2 3
        {8,2,1,8}, //0 start here v=0
        {0,8,1,3}, //1 0*2(-3-1-0 -1
        {0,8,2,4}, //2 0*1(-3-2-0
        {8,5,1,3}, //3 0-2*3(-1-0 -1
        {8,2,6,4}, //4 0-1*3(-2-0
        {7,5,8,3}, //5 0-2-3*1(-0 -1
        {9,8,6,4}, //6 0-1-3*2(-0
};
static int encRead( int pa, int pb)
{
	int8_t cx = 0; 			// initial state 0
	int errCnt = 0;
	while (errCnt < 1550)
	{
		uint8_t v = digitalRead(pa) | digitalRead(pb)<<1;

		if (v < 4)
		{
			uint8_t nx = stb[cx][v];

			if (nx > 6)
			{
		    if (nx == 8)
		      errCnt++;
				else
					return (8 - (int)nx);
			}
			else
			{
				cx = nx;
			}
		}
		else
		{
			cx = 0;
			errCnt++;
		}
	}

	return 0;
}

void setup()
{
	Serial.begin(9600);

	pinMode( ENC_A, INPUT_PULLUP);
	pinMode( ENC_B, INPUT_PULLUP);

}

const int MAX_VAL = 64*6 -1;

int lastPos = 0;

void loop() {

	unsigned long 	sampleTime = millis();
	int rv = encRead(ENC_A,ENC_B);
	sampleTime = millis() - sampleTime;

	if (rv == 0)
	{
		delay(50);
	}
	else
	{
		lastPos += rv;
		if (sampleTime < 20)
			sampleTime = 20;
		// simulate acceleration
		lastPos += rv*int(9000.0/(sampleTime*sampleTime));

		if (lastPos < 0) lastPos = 0;
		if (lastPos > MAX_VAL) lastPos = MAX_VAL;

		Serial.print(lastPos); Serial.print(" "); Serial.println(sampleTime);

	}

}





                                    
;