Last active
January 1, 2018 16:00
-
-
Save n1ywb/450532cccc5d6233259be2a67ed8e23b to your computer and use it in GitHub Desktop.
feather m0 samd21 externally clocked counter
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
WiFi Web Server | |
A simple web server that shows the value of the analog input pins. | |
using a WiFi shield. | |
This example is written for a network using WPA encryption. For | |
WEP or WPA, change the WiFi.begin() call accordingly. | |
Circuit: | |
* WiFi shield attached | |
* Analog inputs attached to pins A0 through A5 (optional) | |
created 13 July 2010 | |
by dlf (Metodo2 srl) | |
modified 31 May 2012 | |
by Tom Igoe | |
*/ | |
#include <SPI.h> | |
#include <WiFi101.h> | |
#include <ArduinoJson.h> | |
#include <ArduinoHttpServer.h> | |
// #include <samd21g18a.h> | |
#include "wiring_private.h" // pinPeripheral() function | |
#include "arduino_secrets.h" | |
///////please enter your sensitive data in the Secret tab/arduino_secrets.h | |
char ssid[] = SECRET_SSID; // your network SSID (name) | |
char pass[] = SECRET_PASS; // your network password (use for WPA, or use as key for WEP) | |
int keyIndex = 0; // your network key Index number (needed only for WEP) | |
int status = WL_IDLE_STATUS; | |
#define MIN(X,Y) (((X) < (Y)) ? (X) : (Y)) | |
#define MAX(X,Y) (((X) > (Y)) ? (X) : (Y)) | |
#include "types.h" | |
params_t params; | |
void dump_params(JsonObject& root) { | |
root["Kp"] = params.Kp; | |
root["Ki"] = params.Ki; | |
root["Kd"] = params.Kd; | |
root["Ko"] = params.Ko; | |
root["throttle_slew_rate"] = params.throttle_slew_rate; | |
root["mode"] = (int)params.mode; | |
root["speed_cmd"] = params.speed_cmd; | |
root["throttle_cmd"] = params.throttle_cmd; | |
root["speed"] = params.speed; | |
root["previous_speed"] = params.previous_speed; | |
root["throttle"] = params.throttle; | |
root["previous_throttle"] = params.previous_throttle; | |
root["vac"] = params.vac; | |
root["vcc"] = params.vcc; | |
root["amps"] = params.amps; | |
root["tc3_ovf_count"] = params.tc3_ovf_count; | |
root["current_tach"] = params.current_tach; | |
root["previous_tach"] = params.previous_tach; | |
root["pin20"] = digitalRead(20); | |
} | |
void load_params(JsonObject& root) { | |
params.Kp = root["Kp"]; | |
params.Ki = root["Ki"]; | |
params.Kd = root["Kd"]; | |
params.Ko = root["Ko"]; | |
params.throttle_slew_rate = root["throttle_slew_rate"]; | |
params.mode = (tcs_mode_t)((int)root["mode"]); | |
params.speed_cmd = root["speed_cmd"]; | |
params.throttle_cmd = root["throttle_cmd"]; | |
} | |
WiFiServer server(80); | |
void setup_tc3() { | |
// Control loop ISR timer | |
// read 32khz from clock generator 1 | |
// 2^15 / 2^8 / 4 == 32hz | |
// Set TC3 clock source to 32khz xtal and enable | |
Serial.println("disable tc3 irq"); | |
NVIC_DisableIRQ(TC3_IRQn); | |
NVIC_ClearPendingIRQ(TC3_IRQn); | |
Serial.println("disable tc3"); | |
REG_TC3_CTRLA = (uint16_t)(0); | |
while (REG_TC3_STATUS & TC_STATUS_SYNCBUSY) {} | |
Serial.println("disable tc3 clock"); | |
REG_GCLK_CLKCTRL = (uint16_t)(GCLK_CLKCTRL_ID_TCC2_TC3); | |
while (REG_GCLK_CLKCTRL & GCLK_CLKCTRL_CLKEN) {} | |
// Serial.println("set clock gen 8 divider"); | |
// REG_GCLK_GENDIV = (uint32_t)(GCLK_GENDIV_ID(8) | GCLK_GENDIV_DIV(32)); | |
Serial.println("enable clock gen 8, clock to 32khz xtal"); | |
REG_GCLK_GENCTRL = (uint32_t)(GCLK_GENCTRL_ID(8) | GCLK_GENCTRL_SRC_XOSC32K | GCLK_GENCTRL_GENEN); | |
Serial.println("enable tc3 clock"); | |
REG_GCLK_CLKCTRL = (uint16_t)(GCLK_CLKCTRL_ID_TCC2_TC3 | GCLK_CLKCTRL_GEN(8) | GCLK_CLKCTRL_CLKEN); | |
Serial.println("reset tc3"); | |
REG_TC3_CTRLA = (uint16_t)(TC_CTRLA_SWRST); | |
while (REG_TC3_STATUS & TC_STATUS_SYNCBUSY) { | |
delay(1000); | |
Serial.println(REG_TC3_CTRLA & TC_CTRLA_SWRST); | |
} | |
Serial.println("enable tc3"); | |
// 8 bit counter, / 4 prescale, enable | |
REG_TC3_CTRLA = (uint16_t)(TC_CTRLA_MODE_COUNT8 | TC_CTRLA_PRESCALER_DIV4 | TC_CTRLA_ENABLE); | |
Serial.println("enable tc3 interrupt"); | |
// interrupt can be individually enabled by writing a one | |
// to the corresponding bit in the Interrupt Enable Set register (INTENSET), | |
REG_TC3_INTENSET = (uint8_t)(TC_INTENSET_OVF); | |
Serial.println(REG_TC3_INTENSET); | |
// Configure interrupt request | |
NVIC_SetPriority(TC3_IRQn, 0); | |
NVIC_EnableIRQ(TC3_IRQn); | |
} | |
void TC3_Handler(void) { | |
++params.tc3_ovf_count; | |
// control logic goes here | |
if (!TC4->COUNT32.STATUS.bit.SYNCBUSY) { | |
params.previous_tach = params.current_tach; | |
// this read is slow when the tc4 clock is slow; it's fast when the tc4 clock is disabled. | |
params.current_tach = REG_TC4_COUNT32_COUNT; | |
REG_TC4_READREQ = (uint16_t)(TC_READREQ_RREQ | TC_READREQ_ADDR(TC_COUNT32_COUNT_OFFSET)); | |
} | |
REG_TC3_INTFLAG = (uint8_t)(TC_INTFLAG_OVF); | |
} | |
void setup_tc4() { | |
// Tachometer pulse counter; 3/rev | |
// signal path: | |
// port -> gclock io -> gclock controller -> ahb-apb bridge A -> hi speed bus matrix -> ahb-apb bridge C -> TC4/5 | |
// gclock detail: | |
// gclk io -> controller -> generator -> divider/masker -> multiplexer -> gate -> gclk_peripheral -> peripheral | |
// Using the TC’s I/O lines requires the I/O pins to be configured. Refer to “PORT” on page 379 for details. | |
// REG_PORTA | |
// configure arduino pin 20 uc pin 31 multiplex for gclkio[6] | |
// pin 20 drives clock 6 | |
pinMode(20, INPUT_PULLUP); | |
pinPeripheral(20, PIO_AC_CLK); | |
Serial.println("disable tc4"); | |
TC4->COUNT16.CTRLA.reg &= ~TC_CTRLA_ENABLE; | |
while (REG_TC4_STATUS & TC_STATUS_SYNCBUSY); | |
Serial.println("disable tc5"); | |
TC5->COUNT16.CTRLA.reg &= ~TC_CTRLA_ENABLE; | |
while (TC5->COUNT16.STATUS.bit.SYNCBUSY); | |
Serial.println("disable tc5 irq"); | |
NVIC_DisableIRQ(TC5_IRQn); | |
NVIC_ClearPendingIRQ(TC5_IRQn); | |
NVIC_DisableIRQ(TC4_IRQn); | |
NVIC_ClearPendingIRQ(TC4_IRQn); | |
Serial.println("disable tc4 clock"); | |
REG_GCLK_CLKCTRL = (uint16_t)(GCLK_CLKCTRL_ID_TC4_TC5); | |
while (GCLK->STATUS.bit.SYNCBUSY); | |
Serial.println("enable tc4 clock"); | |
// Set clock gen 6 clock source to gclk_io[6] and enable | |
REG_GCLK_GENCTRL = (uint32_t)(GCLK_GENCTRL_ID(6) | GCLK_GENCTRL_SRC_GCLKIN | GCLK_GENCTRL_GENEN); | |
while (GCLK->STATUS.bit.SYNCBUSY); | |
// Clock TC4 to cpu during config | |
REG_GCLK_CLKCTRL = (uint16_t)(GCLK_CLKCTRL_ID_TC4_TC5 | GCLK_CLKCTRL_GEN(0) | GCLK_CLKCTRL_CLKEN); | |
while (GCLK->STATUS.bit.SYNCBUSY); | |
//z The mode (8, 16 or 32 bits) of the TC must be selected in the TC Mode bit group in the Control A register | |
//(CTRLA.MODE). The default mode is 16 bits | |
// is this slow? | |
// REG_TC4_READREQ = (uint16_t)(TC_READREQ_RCONT | TC_READREQ_ADDR(TC_COUNT32_COUNT_OFFSET)); | |
Serial.println("reset tc5"); | |
REG_TC5_CTRLA = (uint16_t)(TC_CTRLA_SWRST); | |
while (TC5->COUNT16.STATUS.bit.SYNCBUSY) { | |
delay(1000); | |
Serial.println(REG_TC5_CTRLA & TC_CTRLA_SWRST); | |
} | |
Serial.println("reset tc4"); | |
REG_TC4_CTRLA = (uint16_t)(TC_CTRLA_SWRST); | |
while (TC4->COUNT16.STATUS.bit.SYNCBUSY) { | |
delay(1000); | |
Serial.println(REG_TC4_CTRLA & TC_CTRLA_SWRST); | |
} | |
REG_GCLK_CLKCTRL = (uint16_t)(GCLK_CLKCTRL_ID_TC4_TC5); | |
while (GCLK->STATUS.bit.SYNCBUSY); | |
// return; | |
REG_GCLK_CLKCTRL = (uint16_t)(GCLK_CLKCTRL_ID_TC4_TC5 | GCLK_CLKCTRL_GEN(6) | GCLK_CLKCTRL_CLKEN); | |
while (GCLK->STATUS.bit.SYNCBUSY); | |
Serial.println("enable tc4"); | |
REG_TC4_CTRLA = (uint16_t)(TC_CTRLA_MODE_COUNT32 | TC_CTRLA_ENABLE); | |
} | |
void setup() { | |
WiFi.setPins(8,7,4,2); | |
//Initialize serial and wait for port to open: | |
Serial.begin(9600); | |
delay(2000); | |
// while (!Serial) { | |
// ; // wait for serial port to connect. Needed for native USB port only | |
// } | |
setup_tc4(); | |
setup_tc3(); | |
// check for the presence of the shield: | |
if (WiFi.status() == WL_NO_SHIELD) { | |
Serial.println("WiFi shield not present"); | |
// don't continue: | |
while (true); | |
} | |
// attempt to connect to WiFi network: | |
while (status != WL_CONNECTED) { | |
Serial.print("Attempting to connect to SSID: "); | |
Serial.println(ssid); | |
// Connect to WPA/WPA2 network. Change this line if using open or WEP network: | |
status = WiFi.begin(ssid, pass); | |
// wait 10 seconds for connection: | |
delay(5000); | |
} | |
server.begin(); | |
// you're connected now, so print out the status: | |
printWiFiStatus(); | |
} | |
void sendreply(Client& client) { | |
const size_t bufferSize = JSON_OBJECT_SIZE(18); | |
DynamicJsonBuffer jsonBuffer(bufferSize); | |
JsonObject& root = jsonBuffer.createObject(); | |
dump_params(root); | |
ArduinoHttpServer::StreamHttpReply httpReply(client, "application/json"); | |
while(client.read()>=0); | |
String httpErrorReply("HTTP/1.1 200\r\n"); | |
httpErrorReply += "Connection: close\r\n"; | |
// httpErrorReply += "Content-Length: "; | |
// httpErrorReply += data.length(); httpErrorReply += "\r\n"; | |
httpErrorReply += "Content-Type: application/json\r\n"; | |
httpErrorReply += "\r\n"; | |
// httpErrorReply += data; | |
client.print(httpErrorReply); | |
root.printTo(client); | |
} | |
void loop() { | |
// listen for incoming clients | |
WiFiClient client = server.available(); | |
if (client) { | |
Serial.println("new client"); | |
while (client.connected()) { | |
if (client.available()) { | |
ArduinoHttpServer::StreamHttpRequest<1023> httpRequest(client); | |
// Parse the request. | |
if (httpRequest.readRequest()) | |
{ | |
// Use the information you like they way you like. | |
// Retrieve HTTP resource / URL requested | |
// Retrieve 2nd part of HTTP resource. | |
// E.g.: "on" from "/api/sensors/on" | |
// Serial.println( httpRequest.getResource()[2] ); | |
// Retrieve HTTP method. | |
// E.g.: GET / PUT / HEAD / DELETE / POST | |
ArduinoHttpServer::MethodEnum method( ArduinoHttpServer::MethodInvalid ); | |
method = httpRequest.getMethod(); | |
Serial.println( httpRequest.getResource().toString() ); | |
if( method == ArduinoHttpServer::MethodGet ) | |
{ | |
Serial.println("GET"); | |
sendreply(client); | |
client.stop(); | |
break; | |
} | |
else if( method == ArduinoHttpServer::MethodPost ) | |
{ | |
Serial.println("POST"); | |
const size_t bufferSize = JSON_OBJECT_SIZE(18) + 300; | |
DynamicJsonBuffer jsonBuffer(bufferSize); | |
Serial.println(httpRequest.getBody()); | |
JsonObject& root2 = jsonBuffer.parseObject(httpRequest.getBody()); | |
if (root2.success()) { | |
load_params(root2); | |
sendreply(client); | |
} | |
else { | |
Serial.println("json decoding error"); | |
} | |
client.stop(); | |
break; | |
} | |
} | |
else | |
{ | |
// HTTP parsing failed. Client did not provide correct HTTP data or | |
// client requested an unsupported feature. | |
ArduinoHttpServer::StreamHttpErrorReply httpReply(client, httpRequest.getContentType()); | |
httpReply.send(httpRequest.getErrorDescrition()); | |
client.stop(); | |
break; | |
} | |
} | |
} | |
// give the web browser time to receive the data | |
delay(1); | |
// close the connection: | |
client.stop(); | |
Serial.println("client disconnected"); | |
} | |
} | |
void printWiFiStatus() { | |
// print the SSID of the network you're attached to: | |
Serial.print("SSID: "); | |
Serial.println(WiFi.SSID()); | |
// print your WiFi shield's IP address: | |
IPAddress ip = WiFi.localIP(); | |
Serial.print("IP Address: "); | |
Serial.println(ip); | |
// print the received signal strength: | |
long rssi = WiFi.RSSI(); | |
Serial.print("signal strength (RSSI):"); | |
Serial.print(rssi); | |
Serial.println(" dBm"); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment