commit c7b801114a5fe6c19248648645e175e1456ded30 Author: Dirk Jahnke Date: Sun Mar 18 17:04:13 2018 +0100 Initial commit diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..dbe9166 --- /dev/null +++ b/.gitignore @@ -0,0 +1,4 @@ +.vscode +build +*.tmp +*.bak diff --git a/README.md b/README.md new file mode 100644 index 0000000..05cafdc --- /dev/null +++ b/README.md @@ -0,0 +1,15 @@ +# Flash light / alarm light controller + +## Overview + +This is an empty app, serves as a skeleton for building Mongoose OS +apps from scratch. + +## How to install this app + +- Install and start [mos tool](https://mongoose-os.com/software.html) +- Switch to the Project page, find and import this app, build and flash it: + +

+ +

diff --git a/fs/index.html b/fs/index.html new file mode 100644 index 0000000..5f37107 --- /dev/null +++ b/fs/index.html @@ -0,0 +1,5 @@ + + +

Welcome to the empty project

+ + diff --git a/mos.yml b/mos.yml new file mode 100644 index 0000000..1e8e760 --- /dev/null +++ b/mos.yml @@ -0,0 +1,71 @@ +author: Dirk Jahnke +description: Flash light / alarm controller +version: 1.0 + +libs_version: ${mos.version} +modules_version: ${mos.version} +mongoose_os_version: ${mos.version} + +# Optional. List of tags for online search. +tags: + - c + +# List of files / directories with C sources. No slashes at the end of dir names. +sources: + - src + +# List of dirs. Files from these dirs will be copied to the device filesystem +filesystem: + - fs + +# Custom configuration entries, settable via "device configuration" +# Below is a custom firmware configuration example. +# Uncomment and modify according to your needs: + +config_schema: +# - ["my_app", "o", {title: "My app custom settings"}] +# - ["my_app.bool_value", "b", false, {title: "Some boolean value"}] +# - ["my_app.string_value", "s", "", {title: "Some string value"}] +# - ["my_app.int_value", "i", 123, {title: "Some integer value"}] + - ["i2c.enable", true] + - ["i2c.freq", 1000] + - ["i2c.sda_gpio", 4] # D2 + - ["i2c.scl_gpio", 5] # D1 + - ["flashLight", "o", {title: "Flash light / alarm light settings"}] + - ["flashLight.address", "i", 0x30, {title: "i2c address of motor controller TB6612 (e.g. WEMOS)"}] + - ["flashLight.mqttCtrlTopic", "s", "flashLight/##boardid##/ctrl", {title: "MQTT channel to subscribe to receive commands"}] + +# These settings get compiled into the C structure, and can be accessed +# from the C code this way: +# +# printf("Hello from %s!\n", mgos_sys_config_get_device_id()); +# +# Settings are cool: can be modified remotely without full firmware upgrade! +# +# To see all available compiled settings, buid the firmware and open +# build/gen/mgos_config.h file. +# +# Also, in this config_schema section, you can override existing +# settings that has been created by other libraries. For example, debug log +# level is 2 by default. For this firmware we can override it to 3: +# +# config_schema: +# - ["debug.level", 3] + + +# List of libraries used by this app, in order of initialisation +libs: + - origin: https://github.com/mongoose-os-libs/ca-bundle + - origin: https://github.com/mongoose-os-libs/rpc-service-config + - origin: https://github.com/mongoose-os-libs/rpc-service-fs + - origin: https://github.com/mongoose-os-libs/rpc-uart + - origin: https://github.com/mongoose-os-libs/i2c + - origin: https://github.com/mongoose-os-libs/spi + - origin: https://github.com/mongoose-os-libs/wifi + - origin: https://github.com/mongoose-os-libs/http-server + - origin: https://github.com/mongoose-os-libs/rpc-loopback + - origin: https://github.com/mongoose-os-libs/rpc-mqtt + - origin: https://github.com/mongoose-os-libs/rpc-service-ota + +# Used by the mos tool to catch mos binaries incompatible with this file format +manifest_version: 2017-05-18 diff --git a/src/WEMOS_Motor.c b/src/WEMOS_Motor.c new file mode 100644 index 0000000..b1f46f8 --- /dev/null +++ b/src/WEMOS_Motor.c @@ -0,0 +1,88 @@ +#include "mgos_system.h" +#include "mgos_i2c.h" +#include "WEMOS_Motor.h" + + +static struct mgos_i2c *i2c; +static uint32_t motor_freq[MAX_NUM_MOTORS]; +static uint16_t motor_i2c_address[MAX_NUM_MOTORS]; +static bool initialized = false; + +void wemos_motor_init() { + if (!initialized) { + i2c = mgos_i2c_get_global(); + initialized = true; + } +} + +/* setfreq() -- set PWM's frequency +motorNumber: 0..n +freq: PWM's frequency +*/ +void wemos_motor_set_freq(uint8_t motorNumber, uint32_t freq) { + uint8_t data[4]; + + wemos_motor_init(); + if (motorNumber < MAX_NUM_MOTORS) { + data[0] = (uint8_t) (freq >> 16) & 0x0f; + data[1] = (uint8_t) (freq >> 16); + data[2] = (uint8_t) (freq >> 8); + data[3] = (uint8_t) freq; + mgos_i2c_write(i2c, motor_i2c_address[motorNumber], data, 4, true); + // mgos_msleep(100); + } else { + // LOG ERROR + } +} + +/* Motor() +motorNumber: 0..n +address: Shield I2C address +freq: PWM's frequency +*/ +void wemos_motor_initMotor(uint8_t motorNumber, uint8_t address, uint32_t freq) { + wemos_motor_init(); + + if (motorNumber < MAX_NUM_MOTORS) { + motor_freq[motorNumber] = freq; + motor_i2c_address[motorNumber] = address; + wemos_motor_set_freq(motorNumber, freq); + } else { + // LOG ERROR + } +} + + +/* setmotor() -- set motor +motorNumber: 0..n +dir: + _SHORT_BRAKE 0 + _CCW 1 + _CCW 2 + _STOP 3 + _STANDBY 4 + +pwm_val: + 0.00 - 100.00 (%) +*/ +void wemos_motor_setmotor(uint8_t motorNumber, uint8_t dir, float pwm_val) +{ + uint16_t _pwm_val; + uint8_t data[4]; + + wemos_motor_init(); + if (motorNumber < MAX_NUM_MOTORS) { + data[0] = (uint8_t) (motorNumber & 0x01) | (uint8_t) 0x10; + data[1] = dir; + _pwm_val = (uint16_t) (pwm_val * 100); + + if(_pwm_val>10000) + _pwm_val=10000; + data[2] = (uint8_t) (_pwm_val >> 8); + data[3] = (uint8_t) _pwm_val; + mgos_i2c_write(i2c, motor_i2c_address[motorNumber], data, 4, true); + // mgos_msleep(100); + } else { + // LOG ERROR + } +} diff --git a/src/WEMOS_Motor.h b/src/WEMOS_Motor.h new file mode 100644 index 0000000..e5e4d4b --- /dev/null +++ b/src/WEMOS_Motor.h @@ -0,0 +1,19 @@ + +#ifndef __WEMOS_MOTOR_H +#define __WEMOS_MOTOR_H + +#define MAX_NUM_MOTORS 2 + +extern void wemos_motor_init(); +extern void wemos_motor_initMotor(uint8_t motorNumber, uint8_t address, uint32_t freq); +extern void wemos_motor_set_freq(uint8_t motorNumber, uint32_t freq); +extern void wemos_motor_setmotor(uint8_t motorNumber, uint8_t dir, float pwm_val); + +#define _SHORT_BRAKE 0 +#define _CCW 1 +#define _CW 2 +#define _STOP 3 +#define _STANDBY 4 + +#endif + diff --git a/src/main.c b/src/main.c new file mode 100644 index 0000000..547c9a8 --- /dev/null +++ b/src/main.c @@ -0,0 +1,148 @@ +#include "mgos.h" +#include "WEMOS_Motor.h" + +#include "mgos_rpc.h" +#include "common/cs_dbg.h" +#include "common/json_utils.h" +#include "common/platform.h" +#include "frozen/frozen.h" +#include "mgos_app.h" +#include "mgos_gpio.h" +#include "mgos_net.h" +#include "mgos_sys_config.h" +#include "mgos_timers.h" + +static float pwm; +static float flashLightSpeed = 50; /* 0.0 .. 100.0 */ + +// Motor numbers +//Motor shiled I2C Address: 0x30 +//PWM frequency: 1000Hz(1kHz) +#define M1 0 +#define M1_addr 0x30 +#define M1_freq 5000 + +static void motor_timer_cb(void *arg) { + if (pwm > flashLightSpeed + 5.0) { + pwm = 0.0; // start again + } else { + wemos_motor_setmotor(M1, _CW, pwm); + LOG(LL_INFO, ("M1, pwm=%f", pwm)); + + pwm += 0.1; + + if (pwm > flashLightSpeed) { + wemos_motor_setmotor(M1, _STOP, 0.0); + LOG(LL_INFO, ("Stopped")); + } + } + (void) arg; +} + +static void flashLightOn(struct mg_rpc_request_info *ri, void *cb_arg, + struct mg_rpc_frame_info *fi, struct mg_str args) { + struct mbuf fb; + struct json_out out = JSON_OUT_MBUF(&fb); + + mbuf_init(&fb, 30); + + /* + int num = 0; + if (json_scanf(args.p, args.len, ri->args_fmt, &num) == 1) { + json_printf(&out, "{num: %d}", num + 1); + } else { + json_printf(&out, "{error: %Q}", "num is required"); + } + */ + json_printf(&out, "{result: 0, resultString: %Q}", "OK"); + + printf("FlashLight ON\n"); + wemos_motor_setmotor(M1, _CW, flashLightSpeed); + + mg_rpc_send_responsef(ri, "%.*s", fb.len, fb.buf); + ri = NULL; + mbuf_free(&fb); + + (void) cb_arg; + (void) fi; + (void) args; +} + +static void flashLightOff(struct mg_rpc_request_info *ri, void *cb_arg, + struct mg_rpc_frame_info *fi, struct mg_str args) { + struct mbuf fb; + struct json_out out = JSON_OUT_MBUF(&fb); + + mbuf_init(&fb, 30); + + /* + int num = 0; + if (json_scanf(args.p, args.len, ri->args_fmt, &num) == 1) { + json_printf(&out, "{num: %d}", num + 1); + } else { + json_printf(&out, "{error: %Q}", "num is required"); + } + */ + json_printf(&out, "{result: 0, resultString: %Q}", "OK"); + + printf("FlashLight OFF\n"); + wemos_motor_setmotor(M1, _STOP, 0); + + mg_rpc_send_responsef(ri, "%.*s", fb.len, fb.buf); + ri = NULL; + mbuf_free(&fb); + + (void) cb_arg; + (void) fi; + (void) args; +} + + +static void flashLightSetSpeed(struct mg_rpc_request_info *ri, void *cb_arg, + struct mg_rpc_frame_info *fi, struct mg_str args) { + struct mbuf fb; + struct json_out out = JSON_OUT_MBUF(&fb); + + mbuf_init(&fb, 40); + + int speed = 0; + + if (json_scanf(args.p, args.len, ri->args_fmt, &speed) == 1) { + flashLightSpeed = (float) speed; + printf("FlashLight set speed tp %d\n", speed); + json_printf(&out, "{result: 0, resultString: %Q, speed: %d}", "OK", speed); + } else { + json_printf(&out, "{error: %Q}", "speed is required"); + } + + mg_rpc_send_responsef(ri, "%.*s", fb.len, fb.buf); + ri = NULL; + mbuf_free(&fb); + + (void) cb_arg; + (void) fi; + (void) args; +} + +void net_changed(int ev, void *evd, void *arg) { + if (ev != MGOS_NET_EV_IP_ACQUIRED) return; + // call_peer(); + (void) evd; + (void) arg; +} + +enum mgos_app_init_result mgos_app_init(void) { + struct mg_rpc *c = mgos_rpc_get_global(); + mg_rpc_add_handler(c, "FlashLight.On", NULL, flashLightOn, NULL); + mg_rpc_add_handler(c, "FlashLight.Off", NULL, flashLightOff, NULL); + mg_rpc_add_handler(c, "FlashLight.Speed", "{num: %d}", flashLightSetSpeed, NULL); + mgos_event_add_group_handler(MGOS_EVENT_GRP_NET, net_changed, NULL); + + wemos_motor_init(); + wemos_motor_initMotor(M1, M1_addr, M1_freq); + LOG(LL_INFO, ("\r\nTest PWM 30 to 100, step 0.1,CW\r\n")); + pwm = 30.0; + mgos_set_timer(200, MGOS_TIMER_REPEAT, motor_timer_cb, NULL); + return MGOS_APP_INIT_SUCCESS; +} +