* reorg to include core and librany deps in project using submodules

* added script to insure submodules and such are setup

* added OTA update support and started on syslog logging

* added syslog logging support & Config saving via SPIFFS/Json file

* start travis builds

* DebugLevel

* added eagle designs

* added enclosure

* update README
This commit is contained in:
liebman 2018-06-12 19:04:20 -07:00 committed by GitHub
parent 245cbc2dea
commit 8a53197001
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
41 changed files with 27111 additions and 34 deletions

20
.gitignore vendored
View File

@ -1,13 +1,15 @@
.metadata
.DS_Store
.ino.cpp
.project
.cproject
.settings
Release
Debug
libraries
core
*.bak
*-bak
spec.d
/.setup_hook.sh
/ESPNTPServer/.ino.cpp
/ESPNTPServer/.project
/ESPNTPServer/.cproject
/ESPNTPServer/.settings
/ESPNTPServer/Release
/ESPNTPServer/Debug
/ESPNTPServer/libraries
/ESPNTPServer/core
/ESPNTPServer/spec.d
/RemoteSystemsTempFiles

30
.gitmodules vendored
View File

@ -0,0 +1,30 @@
[submodule "hardware/esp8266com/esp8266"]
path = hardware/esp8266com/esp8266
url = https://github.com/esp8266/Arduino.git
[submodule "libraries/DLog"]
path = libraries/DLog
url = https://github.com/liebman/DLog.git
[submodule "libraries/DLogNet"]
path = libraries/DLogNet
url = https://github.com/liebman/DLogNet.git
[submodule "libraries/MicroNMEA"]
path = libraries/MicroNMEA
url = https://github.com/liebman/MicroNMEA.git
branch = handle-empty-date-or-time
[submodule "libraries/WiFiManager"]
path = libraries/WiFiManager
url = https://github.com/liebman/WiFiManager.git
branch = stdfunc
[submodule "libraries/esp8266-oled-ssd1306"]
path = libraries/esp8266-oled-ssd1306
url = https://github.com/liebman/esp8266-oled-ssd1306.git
branch = cleanup-warnings
[submodule "libraries/ESPAsyncUDP"]
path = libraries/ESPAsyncUDP
url = https://github.com/me-no-dev/ESPAsyncUDP.git
[submodule "libraries/Syslog"]
path = libraries/Syslog
url = https://github.com/arcao/Syslog.git
[submodule "libraries/ArduinoJson"]
path = libraries/ArduinoJson
url = https://github.com/bblanchon/ArduinoJson.git

46
.travis.yml Normal file
View File

@ -0,0 +1,46 @@
language: python
- "2.7"
sudo: required
env:
global:
- APPLICATION_FOLDER="${HOME}/arduino-ide"
- SKETCHBOOK_FOLDER="${TRAVIS_BUILD_DIR}"
- ESP8266_DEVICE="esp8266com:esp8266:generic:CpuFrequency=160,CrystalFreq=26,FlashFreq=40,FlashMode=qio,FlashSize=4M1M,led=2,LwIPVariant=v2mss536,Debug=Serial1,DebugLevel=None____"
- ESPNTPSERVER_DIR="${TRAVIS_BUILD_DIR}/ESPNTPServer"
before_install:
- echo HOME is "'${HOME}'"
- id
- cd "${TRAVIS_BUILD_DIR}"
- ./setup.sh
# setup arduino-ci-script
- git clone https://github.com/per1234/arduino-ci-script.git "${HOME}/scripts"
- cd "${HOME}/scripts"
# Get new tags from the remote
- git fetch --tags
# Checkout the latest tag
- git checkout $(git describe --tags `git rev-list --tags --max-count=1`)
- source "${HOME}/scripts/arduino-ci-script.sh"
# Uncomment the following lines to get verbose output for debugging
# 0 (minimum/default) - 2 (maximum) verbosity
#- set_script_verbosity 1
# Turn on verbose output during compilation
#- set_verbose_output_during_compilation "true"
# Don't for library issues that don't affect compilation
- set_library_testing "false"
- set_application_folder "$APPLICATION_FOLDER"
- set_sketchbook_folder "$SKETCHBOOK_FOLDER"
- install_ide "1.8.5"
# make it look like a sketch for arduino
- touch "${ESPNTPSERVER_DIR}/ESPNTPServer.ino"
script:
# build with arduino
- build_sketch "${ESPNTPSERVER_DIR}" "${ESP8266_DEVICE}" "false" "1.8.5"

120
ESPNTPServer/Config.cpp Normal file
View File

@ -0,0 +1,120 @@
/*
* Config.cpp
*
* Created on: Jun 10, 2018
* Author: chris.l
*/
#include "Config.h"
#include "FS.h"
#include "Log.h"
#include "ArduinoJson.h"
static const char* TAG = "Config";
static const char* CONFIG_FILE = "Config.json";
Config::Config() : _syslog_host(), _syslog_port(0)
{
}
Config::~Config()
{
}
bool Config::begin()
{
dlog.info(TAG, "begin: Mounting SPIFFS");
if (!SPIFFS.begin())
{
dlog.warning(TAG, "begin: Formatting SPIFFS!!!!!");
if (SPIFFS.format())
{
dlog.error(TAG, "begin: SPIFFS format failed!");
return false;
}
dlog.info(TAG, "begin: mounting SPIFFS after format!");
if (!SPIFFS.begin())
{
dlog.error(TAG, "begin: SPIFFS mount failed!!!!");
return false;
}
}
return true;
}
bool Config::load()
{
dlog.info(TAG, "load: file: '%s'", CONFIG_FILE);
if (!SPIFFS.exists(CONFIG_FILE))
{
dlog.warning(TAG, "load: config file does not exist!");
return false;
}
File f = SPIFFS.open(CONFIG_FILE, "r");
if (!f)
{
dlog.error(TAG, "load: failed to open config file!");
return false;
}
StaticJsonBuffer<512> buffer;
dlog.debug(TAG, "load: parsing file contents");
JsonObject& root = buffer.parseObject(f);
f.close();
if (!root.success())
{
dlog.error(TAG, "load: fails to parse file!");
return false;
}
strlcpy(_syslog_host, root["syslogHost"]|"", sizeof(_syslog_host));
_syslog_port = root["syslogPort"] | 0;
dlog.info(TAG, "load: config loaded!");
return true;
}
void Config::save()
{
dlog.info(TAG, "save: file: '%s'", CONFIG_FILE);
File f = SPIFFS.open(CONFIG_FILE, "w");
StaticJsonBuffer<512> buffer;
JsonObject& root = buffer.createObject();
root["syslogHost"] = _syslog_host;
root["syslogPort"] = _syslog_port;
root.printTo(f);
f.close();
dlog.info(TAG, "save: config saved");
}
const char* Config::getSyslogHost()
{
return _syslog_host;
}
void Config::setSyslogHost(const char* host)
{
strlcpy(_syslog_host, host, sizeof(_syslog_host));
}
uint16_t Config::getSyslogPort()
{
return _syslog_port;
}
void Config::setSyslogPort(uint16_t port)
{
_syslog_port = port;
}

36
ESPNTPServer/Config.h Normal file
View File

@ -0,0 +1,36 @@
/*
* Config.h
*
* Created on: Jun 10, 2018
* Author: chris.l
*/
#ifndef CONFIG_H_
#define CONFIG_H_
#include "Arduino.h"
class ConfigImpl;
class Config
{
public:
Config();
virtual ~Config();
bool begin();
bool load();
void save();
const char* getSyslogHost();
void setSyslogHost(const char* host);
uint16_t getSyslogPort();
void setSyslogPort(uint16_t port);
private:
char _syslog_host[64];
uint16_t _syslog_port;
};
#endif /* CONFIG_H_ */

View File

@ -122,6 +122,19 @@ void Display::process()
display();
}
void Display::message(const char* fmt, ...)
{
va_list ap;
va_start(ap, fmt);
clear();
align(TEXT_ALIGN_CENTER);
vprint(64, 32, fmt, ap);
display();
va_end(ap);
}
void Display::clear()
{
_dsp.clear();
@ -146,9 +159,13 @@ void Display::print(int16_t x, int16_t y, const char* fmt, ...)
{
va_list ap;
va_start(ap, fmt);
vprint(x, y, fmt, ap);
va_end(ap);
}
void Display::vprint(int16_t x, int16_t y, const char* fmt, va_list ap)
{
vsnprintf(_buffer, DISPLAY_BUFFER_LEN, fmt, ap);
_buffer[DISPLAY_BUFFER_LEN-1] = '\0';
va_end(ap);
_dsp.drawString(x, y, _buffer);
}

View File

@ -24,12 +24,15 @@ public:
void end();
void process();
void message(const char* fmt, ...);
void clear();
void display();
void align(OLEDDISPLAY_TEXT_ALIGNMENT alignment);
void font(const char* fontData);
void print(int16_t x, int16_t y, const char* fmt, ...);
void vprint(int16_t x, int16_t y, const char* fmt, va_list ap);
private:
SSD1306Wire _dsp;
GPS& _gps;

View File

@ -23,15 +23,20 @@
#include "ESPNTPServer.h"
#include "Log.h"
#include "DLogPrintWriter.h"
#include "DLogSyslogWriter.h"
#include "GPS.h"
#include "NTP.h"
#include "Display.h"
#include "Config.h"
DLog& dlog = DLog::getLog();
GPS gps(Serial, SYNC_PIN);
NTP ntp(gps);
Display display(gps, ntp, SDA_PIN, SCL_PIN);
DLog& dlog = DLog::getLog();
Config config;
char devicename[32];
const char* SETUP_TAG = "setup";
const char* LOOP_TAG = "loop";
@ -54,9 +59,62 @@ void logTimeFirst(DLogBuffer& buffer, DLogLevel level)
tv.tv_usec);
}
void processOTA(const char* ota_url, const char* ota_fp)
{
static PROGMEM const char TAG[] = "processOTA";
dlog.info(FPSTR(TAG), F("OTA update"));
dlog.info(FPSTR(TAG), F("checking for OTA from: '%s'"), ota_url);
display.message("Starting OTA");
ESPhttpUpdate.rebootOnUpdate(false);
t_httpUpdate_return ret;
if (strncmp(ota_url, "https:", 6) == 0)
{
ret = ESPhttpUpdate.update(ota_url, "0.4", ota_fp);
}
else
{
ret = ESPhttpUpdate.update(ota_url, "0.4");
}
String reason = ESPhttpUpdate.getLastErrorString();
switch(ret)
{
case HTTP_UPDATE_OK:
dlog.info(FPSTR(TAG), F("OTA update OK! restarting..."));
dlog.end();
display.message("Success!");
delay(10000);
ESP.restart();
break;
case HTTP_UPDATE_FAILED:
dlog.info(FPSTR(TAG), F("OTA update failed! reason:'%s'"), reason.c_str());
display.message("FAILED!");
delay(10000);
break;
case HTTP_UPDATE_NO_UPDATES:
dlog.info(FPSTR(TAG), F("OTA no updates! reason:'%s'"), reason.c_str());
display.message("NO Update!");
delay(10000);
break;
default:
dlog.info(FPSTR(TAG), F("OTA update WTF? unexpected return code: %d reason: '%s'"), ret, reason.c_str());
display.message("Unknown!");
delay(10000);
break;
}
}
void setup()
{
delay(5000); // delay for IDE to re-open serial
//delay(5000); // delay for IDE to re-open serial
//
// Setup DLog with Serial1, set the pre function to add the date/time
@ -65,32 +123,81 @@ void setup()
dlog.begin(new DLogPrintWriter(Serial1));
dlog.setPreFunc(&logTimeFirst);
//dlog.setLevel("GPS", DLogLevel::DLOG_LEVEL_DEBUG);
dlog.setLevel("Config", DLogLevel::DLOG_LEVEL_DEBUG);
dlog.info(SETUP_TAG, F("Startup!"));
String id = "ESPNTP:" + String(ESP.getChipId(), 16);
strncpy(devicename, id.c_str(), 32);
dlog.info(SETUP_TAG, "Device name: %s", devicename);
dlog.info(SETUP_TAG, F("initializing display"));
display.begin();
dlog.info(SETUP_TAG, F("initializing serial for GPS"));
Serial.begin(9600);
Serial.swap();
dlog.info(SETUP_TAG, F("initializing GPS"));
display.message("Starting GPS");
gps.begin();
display.process();
bool force_config = false;
config.begin();
if (!config.load())
{
dlog.warning(SETUP_TAG, "no config found, forcing config portal!");
force_config = true;
}
// if the reset/config button is pressed then force config
if (digitalRead(CONFIG_PIN) == 0)
{
time_t start = millis();
while (digitalRead(CONFIG_PIN) == 0)
{
time_t delta = millis() - start;
if (!force_config && delta > CONFIG_DELAY)
{
dlog.info(SETUP_TAG, F("reset button held, forcing config!"));
force_config = true;
display.message("Force Config");
}
}
}
#if !defined(USE_NO_WIFI)
dlog.info(SETUP_TAG, F("initializing wifi"));
#if 0
WiFiManager wifi;
wifi.setDebugStream(Serial1);
wifi.setDebugOutput(false);
#else
WiFiManager wifi(Serial1);
wifi.setDebugOutput(true);
#endif
wifi.setDebugOutput(true);
String ssid = "ESPNTPServer" + String(ESP.getChipId());
wifi.autoConnect(ssid.c_str(), NULL);
display.message("Starting WiFi");
WiFiSetup wifi(config, display, Serial1, false, devicename);
wifi.connect(force_config);
const char* syslog_host = config.getSyslogHost();
uint16_t syslog_port = config.getSyslogPort();
if (syslog_host != nullptr && strlen(syslog_host) > 0 && syslog_port != 0)
{
dlog.info(SETUP_TAG, "enabling syslog: '%s:%u'", syslog_host, syslog_port);
dlog.begin(new DLogSyslogWriter("192.168.0.31", 514, devicename));
}
const char* url = wifi.getOTAURL();
const char* fp = wifi.getOTAFP();
if (fp == nullptr)
{
fp = "";
}
if (url != nullptr)
{
processOTA(url, fp);
}
WiFiMode_t mode = WiFi.getMode();
dlog.error(SETUP_TAG, "WiFi mode: %d", mode);
#endif
display.process();
@ -140,6 +247,14 @@ void loop()
last_ip = ip;
}
#if 0
uint32_t m = millis();
if (m % 1000 == 0)
{
dlog.info("loop", "uptime: %lu millis: %lu", m);
}
#endif
gps.process();
static time_t last_seconds;

View File

@ -27,14 +27,18 @@
#include "Arduino.h"
#include "Ticker.h"
#if !defined(USE_NO_WIFI)
#include "WiFiManager.h"
#include "WiFiSetup.h"
#endif
#include "ESP8266httpUpdate.h"
#include <time.h>
// pin definitions
#define SYNC_PIN 12 // (GPIO12) pin tied to 1hz square wave from GPS
#define SYNC_PIN 12 // GPIO12 pin tied to 1hz square wave from GPS
#define CONFIG_PIN 14 // GPIO14 tied to reset/config button
#define SDA_PIN 4
#define SCL_PIN 5
#define CONFIG_DELAY 1000 // how long to hold the button for config mode.
#endif /* _ESPNTPServer_H_ */

View File

@ -1,7 +1,7 @@
/*
* GPS.cpp
*
* Copyright 2017 Christopher B. Liebman
* Copyright 2018 Christopher B. Liebman
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -116,7 +116,9 @@ void GPS::process()
while (_stream.available() > 0)
{
if (_nmea.process(_stream.read()))
int c = _stream.read();
dlog.trace(TAG, F("c: %c"), c);
if (_nmea.process(c))
{
struct timeval tv;
getTime(&tv);
@ -125,9 +127,9 @@ void GPS::process()
const char * id = _nmea.getMessageID();
//
// if it was a GGA and its valid then check and maybe update the time
// if it was a RMC and its valid then check and maybe update the time
//
if (_nmea.getYear() > 2000 && strcmp("RMC", id) == 0)
if (_nmea.getYear() > 2017 && strcmp("RMC", id) == 0)
{
struct tm tm;
tm.tm_year = _nmea.getYear() - 1900;
@ -174,7 +176,7 @@ void GPS::process()
}
else /* nmea not valid or sat count < 4 */
{
if (_gps_valid)
if (_gps_valid || _valid_delay)
{
invalidate("NMEA:%s SATS:%d from: '%s'",
_nmea.isValid() ? "valid" : "invalid",
@ -220,6 +222,7 @@ void ICACHE_RAM_ATTR GPS::invalidate(const char* fmt, ...)
}
_valid = false;
_gps_valid = false;
_valid_delay = 0;
_last_micros = 0;
}

View File

@ -26,7 +26,7 @@
#include "Ticker.h"
#define REASON_SIZE 128
#define NMEA_BUFFER_SIZE 128
#define NMEA_BUFFER_SIZE 250
#define PPS_TIMING_PIN 12 // (GPIO12) if defined PPS interrupt will make high during processing
#define VALID_DELAY 120 // delay (seconds) from gps valid to valid
#define VALID_TIMER_MS 1001 // if this timer expires we invalidate!

128
ESPNTPServer/WiFiSetup.cpp Normal file
View File

@ -0,0 +1,128 @@
/*
* WiFiSetup.cpp
*
* Copyright 2018 Christopher B. Liebman
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Created on: May 27, 2018
* Author: chris.l
*/
#include "WiFiSetup.h"
#include <functional>
#include "Log.h"
static const char* TAG = "WiFiSetup";
WiFiSetup::WiFiSetup(Config& config, Display& display, Stream& serial, boolean debug, const char* devicename)
: _config(config),
_display(display),
_wm(serial),
_ota_url("ota_url", "OTA URL", "", 128),
_ota_fp("ota_fp", "OTA Fingerprint", "", 64),
_syslog_host("syslog_host", "Syslog Host", "", 64),
_syslog_port("syslog_port", "Syslog Port", "514", 8),
_devicename(devicename)
{
_wm.setDebugOutput(debug);
using namespace std::placeholders;
_wm.setAPCallback(std::bind(&WiFiSetup::startingPortal, this, _1));
_wm.setSaveConfigCallback(std::bind(&WiFiSetup::saveConfig, this));
}
WiFiSetup::~WiFiSetup()
{
}
void WiFiSetup::connect(bool force_config)
{
WiFi.mode(WiFiMode::WIFI_STA);
if (force_config)
{
dlog.info(TAG, F("connect: starting forced config portal!"));
_wm.startConfigPortal(_devicename, NULL);
}
else
{
dlog.info(TAG, F("connect: auto-connecting"));
_wm.autoConnect(_devicename, NULL);
}
}
void WiFiSetup::startingPortal(WiFiManager* wmp)
{
(void) wmp;
dlog.info(TAG, F("startingPortal: updating param values"));
_syslog_host.setValue(_config.getSyslogHost(), 64);
char value[10];
snprintf(value, sizeof(value), "%u", _config.getSyslogPort());
_syslog_port.setValue(value, 8);
dlog.info(TAG, F("startingPortal: adding params"));
_wm.addParameter(&_ota_url);
_wm.addParameter(&_ota_fp);
_wm.addParameter(&_syslog_host);
_wm.addParameter(&_syslog_port);
dlog.debug(TAG, F("startingPortal: params added!"));
//
// Update the display with the SSID to show portal is up
//
dlog.info(TAG, F("startingPortal: updating display"));
_display.message("SSID: %s", _wm.getConfigPortalSSID().c_str());
}
void WiFiSetup::saveConfig()
{
dlog.info(TAG, "saveConfig: updating values");
_config.setSyslogHost(_syslog_host.getValue());
_config.setSyslogPort(atoi(_syslog_port.getValue()));
dlog.debug(TAG, "saveConfig: saving!");
_config.save();
}
const char* WiFiSetup::getParam(WiFiManagerParameter& param)
{
const char* value = param.getValue();
if (strlen(value) > 0)
{
return value;
}
return NULL;
}
const char* WiFiSetup::getOTAURL()
{
return getParam(_ota_url);
}
const char* WiFiSetup::getOTAFP()
{
return getParam(_ota_fp);
}
const char* WiFiSetup::getSyslogHost()
{
return getParam(_syslog_host);
}
uint16_t WiFiSetup::getSyslogPort()
{
const char* value = getParam(_syslog_port);
int port = atoi(value);
return port;
}

54
ESPNTPServer/WiFiSetup.h Normal file
View File

@ -0,0 +1,54 @@
/*
* WiFiSetup.h
*
* Copyright 2018 Christopher B. Liebman
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Created on: May 27, 2018
* Author: chris.l
*/
#ifndef WIFISETUP_H_
#define WIFISETUP_H_
#include "Arduino.h"
#include "WiFiManager.h"
#include "Display.h"
#include "Config.h"
class WiFiSetup {
public:
WiFiSetup(Config& config, Display& display, Stream& serial, boolean debug, const char* devicename);
virtual ~WiFiSetup();
void connect(bool force_config = false);
const char* getOTAURL();
const char* getOTAFP();
const char* getSyslogHost();
uint16_t getSyslogPort();
private:
Config& _config;
Display& _display;
WiFiManager _wm;
WiFiManagerParameter _ota_url;
WiFiManagerParameter _ota_fp;
WiFiManagerParameter _syslog_host;
WiFiManagerParameter _syslog_port;
const char* _devicename;
void startingPortal(WiFiManager* wmp);
void saveConfig();
const char*getParam(WiFiManagerParameter& param);
};
#endif /* WIFISETUP_H_ */

View File

@ -1,6 +1,22 @@
# ESPNTPServer
GPS fueled ESP8266 based NTP Server
GPS: any with standard NMEA sentences & a pulse per second signal..
[![Build Status](https://travis-ci.org/liebman/ESPNTPServer.svg?branch=master)](https://travis-ci.org/liebman/ESPNTPServer.svg)
Work in progress....
[ESPNTPServer](ESPNTPServer) Contains the code for the NTP Server
[hardware](hardware) contains the esp8266 arduino core version used as a git submodule
[libraries](libraries) has all needed libraries as git submodules
[eagle](eagle) contains the schematic and board designs in Eagle cad.
[enclosure](enclosure) contains the STL files for the enclosure.
This is designed around [this GPS module](https://www.amazon.com/gp/product/B075DD5746/) but any module with standard NMEA output and a pult per second signal will work if you redesign the board or use an adapter.
I also used [this display module](https://www.amazon.com/gp/product/B00O2KDQBE/). You can use others but be careful with the power polarity, I have modules where VCC and ground pins are in a different order.
![Schematic](images/ESPNTPServer.png)
![assembly](images/open.png)
![running](images/closed.png)

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,194 @@
{
"author": {
"email": "liebman@zod.com",
"name": "Chris Liebman"
},
"description": {
"EN": "EAGLE default 2 layer CAM job."
},
"output_type": "zip",
"outputs": [
{
"format_specifier": {
"decimal": 3,
"integer": 3
},
"output_type": "drill",
"outputs": [
{
"drills": {
"NPTH": true,
"PTH": true,
"VIA": true
},
"filename_format": "outputs/drills.xln",
"layers": {
"from": 1,
"to": 16
},
"name": "Excellon",
"type": "excellon"
}
]
},
{
"filename_prefix": "outputs",
"format_specifier": {
"decimal": 4,
"integer": 3
},
"generate_job_file": true,
"output_type": "gerber",
"outputs": [
{
"board_outline": false,
"config": {
"file_function": "Copper",
"layer": 1,
"layer_details": "mixed",
"layer_type": "top"
},
"filename_format": "%PREFIX/copper_top.gbr",
"layers": [
1,
18,
17
],
"name": "Top Copper",
"polarity": "positive",
"type": "gerber_layer"
},
{
"board_outline": false,
"config": {
"file_function": "Copper",
"layer": 2,
"layer_details": "mixed",
"layer_type": "bottom"
},
"filename_format": "%PREFIX/copper_bottom.gbr",
"layers": [
16,
17,
18
],
"name": "Bottom Copper",
"polarity": "positive",
"type": "gerber_layer"
},
{
"board_outline": true,
"config": {
"file_function": "Profile",
"plating": "non-plated"
},
"filename_format": "%PREFIX/profile.gbr",
"layers": [
],
"milling": true,
"polarity": "positive",
"type": "gerber_layer"
},
{
"board_outline": false,
"config": {
"file_function": "Soldermask",
"index": 1,
"layer_type": "top"
},
"filename_format": "%PREFIX/soldermask_top.gbr",
"layers": [
29
],
"name": "Soldermask Top",
"polarity": "negative",
"type": "gerber_layer"
},
{
"board_outline": false,
"config": {
"file_function": "Soldermask",
"index": 1,
"layer_type": "bottom"
},
"filename_format": "%PREFIX/soldermask_bottom.gbr",
"layers": [
30
],
"name": "Soldermask Bottom",
"polarity": "negative",
"type": "gerber_layer"
},
{
"board_outline": false,
"config": {
"file_function": "Paste",
"layer_type": "top"
},
"filename_format": "%PREFIX/solderpaste_top.gbr",
"layers": [
31
],
"milling": false,
"name": "Solderpaste Top",
"polarity": "positive",
"type": "gerber_layer"
},
{
"board_outline": false,
"config": {
"file_function": "Paste",
"layer_type": "bottom"
},
"filename_format": "%PREFIX/solderpaste_bottom.gbr",
"layers": [
32
],
"milling": false,
"name": "Solderpaste Bottom",
"polarity": "positive",
"type": "gerber_layer"
},
{
"board_outline": false,
"config": {
"file_function": "Legend",
"index": 1,
"layer_type": "top"
},
"filename_format": "%PREFIX/silkscreen_top.gbr",
"layers": [
21,
25
],
"milling": false,
"name": "Silkscreen Top",
"polarity": "positive",
"type": "gerber_layer"
},
{
"board_outline": false,
"config": {
"file_function": "Legend",
"index": 1,
"layer_type": "bottom"
},
"filename_format": "%PREFIX/silkscreen_bottom.gbr",
"layers": [
22,
26
],
"milling": false,
"name": "Silkscreen Bottom",
"polarity": "positive",
"type": "gerber_layer"
}
],
"version": "X2"
}
],
"timestamp": "2018-05-27T17:04:39",
"type": "EAGLE CAM job",
"units": "metric",
"version": "8.6.1"
}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,365 @@
[Eagle]
Version="09 00 01"
Platform="Mac OS X"
Globals="Globals"
Desktop="Desktop"
[Globals]
AutoSaveProject=1
UsedLibraryUrn="urn:adsk.eagle:library:79"
UsedLibraryUrn="urn:adsk.eagle:library:88"
UsedLibraryUrn="urn:adsk.eagle:library:178"
UsedLibraryUrn="urn:adsk.eagle:library:179"
UsedLibraryUrn="urn:adsk.eagle:library:180"
UsedLibraryUrn="urn:adsk.eagle:library:181"
UsedLibraryUrn="urn:adsk.eagle:library:182"
UsedLibraryUrn="urn:adsk.eagle:library:183"
UsedLibraryUrn="urn:adsk.eagle:library:184"
UsedLibraryUrn="urn:adsk.eagle:library:185"
UsedLibraryUrn="urn:adsk.eagle:library:186"
UsedLibraryUrn="urn:adsk.eagle:library:187"
UsedLibraryUrn="urn:adsk.eagle:library:89"
UsedLibraryUrn="urn:adsk.eagle:library:188"
UsedLibraryUrn="urn:adsk.eagle:library:189"
UsedLibraryUrn="urn:adsk.eagle:library:190"
UsedLibraryUrn="urn:adsk.eagle:library:191"
UsedLibraryUrn="urn:adsk.eagle:library:192"
UsedLibraryUrn="urn:adsk.eagle:library:193"
UsedLibraryUrn="urn:adsk.eagle:library:194"
UsedLibraryUrn="urn:adsk.eagle:library:195"
UsedLibraryUrn="urn:adsk.eagle:library:196"
UsedLibraryUrn="urn:adsk.eagle:library:197"
UsedLibraryUrn="urn:adsk.eagle:library:90"
UsedLibraryUrn="urn:adsk.eagle:library:198"
UsedLibraryUrn="urn:adsk.eagle:library:199"
UsedLibraryUrn="urn:adsk.eagle:library:200"
UsedLibraryUrn="urn:adsk.eagle:library:201"
UsedLibraryUrn="urn:adsk.eagle:library:202"
UsedLibraryUrn="urn:adsk.eagle:library:203"
UsedLibraryUrn="urn:adsk.eagle:library:204"
UsedLibraryUrn="urn:adsk.eagle:library:205"
UsedLibraryUrn="urn:adsk.eagle:library:206"
UsedLibraryUrn="urn:adsk.eagle:library:207"
UsedLibraryUrn="urn:adsk.eagle:library:91"
UsedLibraryUrn="urn:adsk.eagle:library:208"
UsedLibraryUrn="urn:adsk.eagle:library:209"
UsedLibraryUrn="urn:adsk.eagle:library:210"
UsedLibraryUrn="urn:adsk.eagle:library:211"
UsedLibraryUrn="urn:adsk.eagle:library:212"
UsedLibraryUrn="urn:adsk.eagle:library:213"
UsedLibraryUrn="urn:adsk.eagle:library:214"
UsedLibraryUrn="urn:adsk.eagle:library:215"
UsedLibraryUrn="urn:adsk.eagle:library:216"
UsedLibraryUrn="urn:adsk.eagle:library:217"
UsedLibraryUrn="urn:adsk.eagle:library:92"
UsedLibraryUrn="urn:adsk.eagle:library:218"
UsedLibraryUrn="urn:adsk.eagle:library:219"
UsedLibraryUrn="urn:adsk.eagle:library:220"
UsedLibraryUrn="urn:adsk.eagle:library:221"
UsedLibraryUrn="urn:adsk.eagle:library:222"
UsedLibraryUrn="urn:adsk.eagle:library:223"
UsedLibraryUrn="urn:adsk.eagle:library:224"
UsedLibraryUrn="urn:adsk.eagle:library:225"
UsedLibraryUrn="urn:adsk.eagle:library:226"
UsedLibraryUrn="urn:adsk.eagle:library:227"
UsedLibraryUrn="urn:adsk.eagle:library:93"
UsedLibraryUrn="urn:adsk.eagle:library:228"
UsedLibraryUrn="urn:adsk.eagle:library:229"
UsedLibraryUrn="urn:adsk.eagle:library:230"
UsedLibraryUrn="urn:adsk.eagle:library:231"
UsedLibraryUrn="urn:adsk.eagle:library:232"
UsedLibraryUrn="urn:adsk.eagle:library:233"
UsedLibraryUrn="urn:adsk.eagle:library:234"
UsedLibraryUrn="urn:adsk.eagle:library:235"
UsedLibraryUrn="urn:adsk.eagle:library:236"
UsedLibraryUrn="urn:adsk.eagle:library:237"
UsedLibraryUrn="urn:adsk.eagle:library:94"
UsedLibraryUrn="urn:adsk.eagle:library:238"
UsedLibraryUrn="urn:adsk.eagle:library:239"
UsedLibraryUrn="urn:adsk.eagle:library:240"
UsedLibraryUrn="urn:adsk.eagle:library:241"
UsedLibraryUrn="urn:adsk.eagle:library:242"
UsedLibraryUrn="urn:adsk.eagle:library:243"
UsedLibraryUrn="urn:adsk.eagle:library:244"
UsedLibraryUrn="urn:adsk.eagle:library:245"
UsedLibraryUrn="urn:adsk.eagle:library:246"
UsedLibraryUrn="urn:adsk.eagle:library:247"
UsedLibraryUrn="urn:adsk.eagle:library:95"
UsedLibraryUrn="urn:adsk.eagle:library:248"
UsedLibraryUrn="urn:adsk.eagle:library:249"
UsedLibraryUrn="urn:adsk.eagle:library:250"
UsedLibraryUrn="urn:adsk.eagle:library:251"
UsedLibraryUrn="urn:adsk.eagle:library:252"
UsedLibraryUrn="urn:adsk.eagle:library:253"
UsedLibraryUrn="urn:adsk.eagle:library:254"
UsedLibraryUrn="urn:adsk.eagle:library:255"
UsedLibraryUrn="urn:adsk.eagle:library:256"
UsedLibraryUrn="urn:adsk.eagle:library:257"
UsedLibraryUrn="urn:adsk.eagle:library:96"
UsedLibraryUrn="urn:adsk.eagle:library:258"
UsedLibraryUrn="urn:adsk.eagle:library:259"
UsedLibraryUrn="urn:adsk.eagle:library:260"
UsedLibraryUrn="urn:adsk.eagle:library:261"
UsedLibraryUrn="urn:adsk.eagle:library:262"
UsedLibraryUrn="urn:adsk.eagle:library:263"
UsedLibraryUrn="urn:adsk.eagle:library:264"
UsedLibraryUrn="urn:adsk.eagle:library:265"
UsedLibraryUrn="urn:adsk.eagle:library:266"
UsedLibraryUrn="urn:adsk.eagle:library:267"
UsedLibraryUrn="urn:adsk.eagle:library:97"
UsedLibraryUrn="urn:adsk.eagle:library:268"
UsedLibraryUrn="urn:adsk.eagle:library:269"
UsedLibraryUrn="urn:adsk.eagle:library:270"
UsedLibraryUrn="urn:adsk.eagle:library:271"
UsedLibraryUrn="urn:adsk.eagle:library:272"
UsedLibraryUrn="urn:adsk.eagle:library:273"
UsedLibraryUrn="urn:adsk.eagle:library:274"
UsedLibraryUrn="urn:adsk.eagle:library:275"
UsedLibraryUrn="urn:adsk.eagle:library:276"
UsedLibraryUrn="urn:adsk.eagle:library:277"
UsedLibraryUrn="urn:adsk.eagle:library:80"
UsedLibraryUrn="urn:adsk.eagle:library:98"
UsedLibraryUrn="urn:adsk.eagle:library:278"
UsedLibraryUrn="urn:adsk.eagle:library:279"
UsedLibraryUrn="urn:adsk.eagle:library:280"
UsedLibraryUrn="urn:adsk.eagle:library:281"
UsedLibraryUrn="urn:adsk.eagle:library:282"
UsedLibraryUrn="urn:adsk.eagle:library:283"
UsedLibraryUrn="urn:adsk.eagle:library:284"
UsedLibraryUrn="urn:adsk.eagle:library:285"
UsedLibraryUrn="urn:adsk.eagle:library:286"
UsedLibraryUrn="urn:adsk.eagle:library:287"
UsedLibraryUrn="urn:adsk.eagle:library:99"
UsedLibraryUrn="urn:adsk.eagle:library:288"
UsedLibraryUrn="urn:adsk.eagle:library:289"
UsedLibraryUrn="urn:adsk.eagle:library:290"
UsedLibraryUrn="urn:adsk.eagle:library:291"
UsedLibraryUrn="urn:adsk.eagle:library:292"
UsedLibraryUrn="urn:adsk.eagle:library:293"
UsedLibraryUrn="urn:adsk.eagle:library:294"
UsedLibraryUrn="urn:adsk.eagle:library:295"
UsedLibraryUrn="urn:adsk.eagle:library:296"
UsedLibraryUrn="urn:adsk.eagle:library:297"
UsedLibraryUrn="urn:adsk.eagle:library:100"
UsedLibraryUrn="urn:adsk.eagle:library:298"
UsedLibraryUrn="urn:adsk.eagle:library:299"
UsedLibraryUrn="urn:adsk.eagle:library:300"
UsedLibraryUrn="urn:adsk.eagle:library:301"
UsedLibraryUrn="urn:adsk.eagle:library:302"
UsedLibraryUrn="urn:adsk.eagle:library:303"
UsedLibraryUrn="urn:adsk.eagle:library:304"
UsedLibraryUrn="urn:adsk.eagle:library:305"
UsedLibraryUrn="urn:adsk.eagle:library:306"
UsedLibraryUrn="urn:adsk.eagle:library:307"
UsedLibraryUrn="urn:adsk.eagle:library:101"
UsedLibraryUrn="urn:adsk.eagle:library:308"
UsedLibraryUrn="urn:adsk.eagle:library:309"
UsedLibraryUrn="urn:adsk.eagle:library:310"
UsedLibraryUrn="urn:adsk.eagle:library:311"
UsedLibraryUrn="urn:adsk.eagle:library:312"
UsedLibraryUrn="urn:adsk.eagle:library:313"
UsedLibraryUrn="urn:adsk.eagle:library:314"
UsedLibraryUrn="urn:adsk.eagle:library:315"
UsedLibraryUrn="urn:adsk.eagle:library:316"
UsedLibraryUrn="urn:adsk.eagle:library:317"
UsedLibraryUrn="urn:adsk.eagle:library:102"
UsedLibraryUrn="urn:adsk.eagle:library:318"
UsedLibraryUrn="urn:adsk.eagle:library:319"
UsedLibraryUrn="urn:adsk.eagle:library:320"
UsedLibraryUrn="urn:adsk.eagle:library:321"
UsedLibraryUrn="urn:adsk.eagle:library:322"
UsedLibraryUrn="urn:adsk.eagle:library:323"
UsedLibraryUrn="urn:adsk.eagle:library:324"
UsedLibraryUrn="urn:adsk.eagle:library:325"
UsedLibraryUrn="urn:adsk.eagle:library:326"
UsedLibraryUrn="urn:adsk.eagle:library:327"
UsedLibraryUrn="urn:adsk.eagle:library:103"
UsedLibraryUrn="urn:adsk.eagle:library:328"
UsedLibraryUrn="urn:adsk.eagle:library:329"
UsedLibraryUrn="urn:adsk.eagle:library:330"
UsedLibraryUrn="urn:adsk.eagle:library:331"
UsedLibraryUrn="urn:adsk.eagle:library:332"
UsedLibraryUrn="urn:adsk.eagle:library:333"
UsedLibraryUrn="urn:adsk.eagle:library:334"
UsedLibraryUrn="urn:adsk.eagle:library:335"
UsedLibraryUrn="urn:adsk.eagle:library:336"
UsedLibraryUrn="urn:adsk.eagle:library:337"
UsedLibraryUrn="urn:adsk.eagle:library:104"
UsedLibraryUrn="urn:adsk.eagle:library:338"
UsedLibraryUrn="urn:adsk.eagle:library:339"
UsedLibraryUrn="urn:adsk.eagle:library:340"
UsedLibraryUrn="urn:adsk.eagle:library:341"
UsedLibraryUrn="urn:adsk.eagle:library:342"
UsedLibraryUrn="urn:adsk.eagle:library:343"
UsedLibraryUrn="urn:adsk.eagle:library:344"
UsedLibraryUrn="urn:adsk.eagle:library:345"
UsedLibraryUrn="urn:adsk.eagle:library:346"
UsedLibraryUrn="urn:adsk.eagle:library:347"
UsedLibraryUrn="urn:adsk.eagle:library:105"
UsedLibraryUrn="urn:adsk.eagle:library:348"
UsedLibraryUrn="urn:adsk.eagle:library:349"
UsedLibraryUrn="urn:adsk.eagle:library:350"
UsedLibraryUrn="urn:adsk.eagle:library:351"
UsedLibraryUrn="urn:adsk.eagle:library:352"
UsedLibraryUrn="urn:adsk.eagle:library:353"
UsedLibraryUrn="urn:adsk.eagle:library:354"
UsedLibraryUrn="urn:adsk.eagle:library:355"
UsedLibraryUrn="urn:adsk.eagle:library:356"
UsedLibraryUrn="urn:adsk.eagle:library:357"
UsedLibraryUrn="urn:adsk.eagle:library:106"
UsedLibraryUrn="urn:adsk.eagle:library:358"
UsedLibraryUrn="urn:adsk.eagle:library:359"
UsedLibraryUrn="urn:adsk.eagle:library:360"
UsedLibraryUrn="urn:adsk.eagle:library:361"
UsedLibraryUrn="urn:adsk.eagle:library:362"
UsedLibraryUrn="urn:adsk.eagle:library:363"
UsedLibraryUrn="urn:adsk.eagle:library:364"
UsedLibraryUrn="urn:adsk.eagle:library:365"
UsedLibraryUrn="urn:adsk.eagle:library:366"
UsedLibraryUrn="urn:adsk.eagle:library:367"
UsedLibraryUrn="urn:adsk.eagle:library:107"
UsedLibraryUrn="urn:adsk.eagle:library:368"
UsedLibraryUrn="urn:adsk.eagle:library:369"
UsedLibraryUrn="urn:adsk.eagle:library:370"
UsedLibraryUrn="urn:adsk.eagle:library:371"
UsedLibraryUrn="urn:adsk.eagle:library:372"
UsedLibraryUrn="urn:adsk.eagle:library:373"
UsedLibraryUrn="urn:adsk.eagle:library:374"
UsedLibraryUrn="urn:adsk.eagle:library:375"
UsedLibraryUrn="urn:adsk.eagle:library:376"
UsedLibraryUrn="urn:adsk.eagle:library:377"
UsedLibraryUrn="urn:adsk.eagle:library:81"
UsedLibraryUrn="urn:adsk.eagle:library:108"
UsedLibraryUrn="urn:adsk.eagle:library:378"
UsedLibraryUrn="urn:adsk.eagle:library:379"
UsedLibraryUrn="urn:adsk.eagle:library:380"
UsedLibraryUrn="urn:adsk.eagle:library:381"
UsedLibraryUrn="urn:adsk.eagle:library:382"
UsedLibraryUrn="urn:adsk.eagle:library:383"
UsedLibraryUrn="urn:adsk.eagle:library:384"
UsedLibraryUrn="urn:adsk.eagle:library:385"
UsedLibraryUrn="urn:adsk.eagle:library:386"
UsedLibraryUrn="urn:adsk.eagle:library:387"
UsedLibraryUrn="urn:adsk.eagle:library:109"
UsedLibraryUrn="urn:adsk.eagle:library:388"
UsedLibraryUrn="urn:adsk.eagle:library:389"
UsedLibraryUrn="urn:adsk.eagle:library:390"
UsedLibraryUrn="urn:adsk.eagle:library:391"
UsedLibraryUrn="urn:adsk.eagle:library:392"
UsedLibraryUrn="urn:adsk.eagle:library:393"
UsedLibraryUrn="urn:adsk.eagle:library:394"
UsedLibraryUrn="urn:adsk.eagle:library:395"
UsedLibraryUrn="urn:adsk.eagle:library:396"
UsedLibraryUrn="urn:adsk.eagle:library:397"
UsedLibraryUrn="urn:adsk.eagle:library:110"
UsedLibraryUrn="urn:adsk.eagle:library:398"
UsedLibraryUrn="urn:adsk.eagle:library:399"
UsedLibraryUrn="urn:adsk.eagle:library:400"
UsedLibraryUrn="urn:adsk.eagle:library:401"
UsedLibraryUrn="urn:adsk.eagle:library:402"
UsedLibraryUrn="urn:adsk.eagle:library:403"
UsedLibraryUrn="urn:adsk.eagle:library:404"
UsedLibraryUrn="urn:adsk.eagle:library:405"
UsedLibraryUrn="urn:adsk.eagle:library:406"
UsedLibraryUrn="urn:adsk.eagle:library:407"
UsedLibraryUrn="urn:adsk.eagle:library:111"
UsedLibraryUrn="urn:adsk.eagle:library:408"
UsedLibraryUrn="urn:adsk.eagle:library:409"
UsedLibraryUrn="urn:adsk.eagle:library:410"
UsedLibraryUrn="urn:adsk.eagle:library:411"
UsedLibraryUrn="urn:adsk.eagle:library:412"
UsedLibraryUrn="urn:adsk.eagle:library:413"
UsedLibraryUrn="urn:adsk.eagle:library:414"
UsedLibraryUrn="urn:adsk.eagle:library:415"
UsedLibraryUrn="urn:adsk.eagle:library:416"
UsedLibraryUrn="urn:adsk.eagle:library:417"
UsedLibraryUrn="urn:adsk.eagle:library:112"
UsedLibraryUrn="urn:adsk.eagle:library:418"
UsedLibraryUrn="urn:adsk.eagle:library:419"
UsedLibraryUrn="urn:adsk.eagle:library:527439"
UsedLibraryUrn="urn:adsk.eagle:library:536"
UsedLibraryUrn="urn:adsk.eagle:library:531"
UsedLibraryUrn="urn:adsk.eagle:library:518"
UsedLibraryUrn="urn:adsk.eagle:library:113"
UsedLibraryUrn="urn:adsk.eagle:library:114"
UsedLibraryUrn="urn:adsk.eagle:library:115"
UsedLibraryUrn="urn:adsk.eagle:library:116"
UsedLibraryUrn="urn:adsk.eagle:library:117"
UsedLibraryUrn="urn:adsk.eagle:library:82"
UsedLibraryUrn="urn:adsk.eagle:library:118"
UsedLibraryUrn="urn:adsk.eagle:library:119"
UsedLibraryUrn="urn:adsk.eagle:library:120"
UsedLibraryUrn="urn:adsk.eagle:library:121"
UsedLibraryUrn="urn:adsk.eagle:library:122"
UsedLibraryUrn="urn:adsk.eagle:library:123"
UsedLibraryUrn="urn:adsk.eagle:library:124"
UsedLibraryUrn="urn:adsk.eagle:library:125"
UsedLibraryUrn="urn:adsk.eagle:library:126"
UsedLibraryUrn="urn:adsk.eagle:library:127"
UsedLibraryUrn="urn:adsk.eagle:library:83"
UsedLibraryUrn="urn:adsk.eagle:library:128"
UsedLibraryUrn="urn:adsk.eagle:library:129"
UsedLibraryUrn="urn:adsk.eagle:library:130"
UsedLibraryUrn="urn:adsk.eagle:library:131"
UsedLibraryUrn="urn:adsk.eagle:library:132"
UsedLibraryUrn="urn:adsk.eagle:library:133"
UsedLibraryUrn="urn:adsk.eagle:library:134"
UsedLibraryUrn="urn:adsk.eagle:library:135"
UsedLibraryUrn="urn:adsk.eagle:library:136"
UsedLibraryUrn="urn:adsk.eagle:library:137"
UsedLibraryUrn="urn:adsk.eagle:library:84"
UsedLibraryUrn="urn:adsk.eagle:library:138"
UsedLibraryUrn="urn:adsk.eagle:library:139"
UsedLibraryUrn="urn:adsk.eagle:library:140"
UsedLibraryUrn="urn:adsk.eagle:library:141"
UsedLibraryUrn="urn:adsk.eagle:library:142"
UsedLibraryUrn="urn:adsk.eagle:library:143"
UsedLibraryUrn="urn:adsk.eagle:library:144"
UsedLibraryUrn="urn:adsk.eagle:library:145"
UsedLibraryUrn="urn:adsk.eagle:library:146"
UsedLibraryUrn="urn:adsk.eagle:library:147"
UsedLibraryUrn="urn:adsk.eagle:library:85"
UsedLibraryUrn="urn:adsk.eagle:library:148"
UsedLibraryUrn="urn:adsk.eagle:library:149"
UsedLibraryUrn="urn:adsk.eagle:library:150"
UsedLibraryUrn="urn:adsk.eagle:library:151"
UsedLibraryUrn="urn:adsk.eagle:library:152"
UsedLibraryUrn="urn:adsk.eagle:library:153"
UsedLibraryUrn="urn:adsk.eagle:library:154"
UsedLibraryUrn="urn:adsk.eagle:library:155"
UsedLibraryUrn="urn:adsk.eagle:library:156"
UsedLibraryUrn="urn:adsk.eagle:library:157"
UsedLibraryUrn="urn:adsk.eagle:library:86"
UsedLibraryUrn="urn:adsk.eagle:library:158"
UsedLibraryUrn="urn:adsk.eagle:library:159"
UsedLibraryUrn="urn:adsk.eagle:library:160"
UsedLibraryUrn="urn:adsk.eagle:library:161"
UsedLibraryUrn="urn:adsk.eagle:library:162"
UsedLibraryUrn="urn:adsk.eagle:library:163"
UsedLibraryUrn="urn:adsk.eagle:library:164"
UsedLibraryUrn="urn:adsk.eagle:library:165"
UsedLibraryUrn="urn:adsk.eagle:library:166"
UsedLibraryUrn="urn:adsk.eagle:library:167"
UsedLibraryUrn="urn:adsk.eagle:library:87"
UsedLibraryUrn="urn:adsk.eagle:library:168"
UsedLibraryUrn="urn:adsk.eagle:library:169"
UsedLibraryUrn="urn:adsk.eagle:library:170"
UsedLibraryUrn="urn:adsk.eagle:library:171"
UsedLibraryUrn="urn:adsk.eagle:library:172"
UsedLibraryUrn="urn:adsk.eagle:library:173"
UsedLibraryUrn="urn:adsk.eagle:library:174"
UsedLibraryUrn="urn:adsk.eagle:library:175"
UsedLibraryUrn="urn:adsk.eagle:library:176"
UsedLibraryUrn="urn:adsk.eagle:library:177"
UsedLibrary="/Users/chris.l/Dropbox/Eagle/lbr/MCP1825.lbr"
UsedLibrary="/Users/chris.l/Dropbox/Eagle/SynchroClock/SynchroClock.lbr"
UsedLibrary="/Users/chris.l/Dropbox/Eagle/lbr/SparkFun-Eagle-Libraries/SparkFun-Connectors.lbr"
UsedLibrary="ESPNTPServer.lbr"
[Win_1]
Type="Control Panel"
Number=0
[Desktop]
Screen="1680 1050"
Window="Win_1"

BIN
enclosure/Bottom-0.5v33.stl Normal file

Binary file not shown.

BIN
enclosure/Top-0.5v33.stl Normal file

Binary file not shown.

@ -0,0 +1 @@
Subproject commit 9c5c16e9c8d90c3bd21a756c3a1487f3826b6e24

BIN
images/ESPNTPServer.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 72 KiB

BIN
images/closed.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 10 MiB

BIN
images/open.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 MiB

1
libraries/ArduinoJson Submodule

@ -0,0 +1 @@
Subproject commit 7b229e4c3810c65fc3c5620a42fc3f934d7f1b59

1
libraries/DLog Submodule

@ -0,0 +1 @@
Subproject commit 733b67f7c650e5f6652172b7194b3044d8d73ee4

1
libraries/DLogNet Submodule

@ -0,0 +1 @@
Subproject commit 26fd5f194b978ae19b5726022410b9cc86cfeb1d

1
libraries/ESPAsyncUDP Submodule

@ -0,0 +1 @@
Subproject commit b592ac6e93e9dbfd61db70ce80dcd04a2afcc76a

1
libraries/MicroNMEA Submodule

@ -0,0 +1 @@
Subproject commit 87d5508cc105be222cc62f090742b2b26ea580bc

1
libraries/Syslog Submodule

@ -0,0 +1 @@
Subproject commit 9f1a2506b38e49312f2b353559ef4eca11616975

1
libraries/WiFiManager Submodule

@ -0,0 +1 @@
Subproject commit 2d194ea518e22424d12418d8a7b36ff4406dec5c

@ -0,0 +1 @@
Subproject commit ca4e8b7d2e7062475686181cc01251bffa67dcce

11
setup.sh Executable file
View File

@ -0,0 +1,11 @@
#!/bin/sh
git submodule init
git submodule update
test -x .setup_hook.sh && ./.setup_hook.sh
cd hardware/esp8266com/esp8266
git submodule init
git submodule update
cd tools
./get.py