Not AirTag, But ESP32Tag

This commit is contained in:
Eric
2022-01-29 23:03:59 -08:00
parent 69c85b76c2
commit af7db64fcb
3 changed files with 371 additions and 0 deletions

View File

@@ -0,0 +1,256 @@
/////////////////////////////////////////////////////////////////
/*
Not AirTag, But ESP32Tag
For More Information: https://youtu.be/_Bu3lw49m5s
Created by Eric N. (ThatProject)
*/
/////////////////////////////////////////////////////////////////
#include <math.h>
#include <lvgl.h>
#include "MyDisplaySetup.h"
static void (*functionPointer)(float);
#include "MyDW1000Ranging.h"
static const uint32_t screenWidth = 320;
static const uint32_t screenHeight = 480;
static lv_disp_draw_buf_t draw_buf;
static lv_color_t buf[screenWidth * 10];
static portMUX_TYPE mux = portMUX_INITIALIZER_UNLOCKED;
static const uint16_t timer_divider = 80;
static const uint64_t timer_max_count = 1000;
static hw_timer_t *timer = NULL;
static SemaphoreHandle_t bin_sem = NULL;
uint32_t cp0_regs[18];
void IRAM_ATTR onTimer() {
uint32_t cp_state = xthal_get_cpenable();
if (cp_state) {
xthal_save_cp0(cp0_regs);
} else {
xthal_set_cpenable(1);
}
portENTER_CRITICAL_ISR(&mux);
DW1000Ranging.loop();
portEXIT_CRITICAL_ISR(&mux);
BaseType_t task_woken = pdFALSE;
xSemaphoreGiveFromISR(bin_sem, &task_woken);
if (task_woken == pdTRUE) {
portYIELD_FROM_ISR();
}
if (cp_state) {
xthal_restore_cp0(cp0_regs);
} else {
xthal_set_cpenable(0);
}
}
void my_disp_flush(lv_disp_drv_t *disp, const lv_area_t *area, lv_color_t *color_p) {
uint32_t w = (area->x2 - area->x1 + 1);
uint32_t h = (area->y2 - area->y1 + 1);
tft.startWrite();
tft.setAddrWindow(area->x1, area->y1, w, h);
tft.writePixels((lgfx::rgb565_t *)&color_p->full, w * h);
tft.endWrite();
lv_disp_flush_ready(disp);
}
void setup() {
Serial.begin(115200);
functionPointer = &updateRange;
tft.begin();
tft.setRotation(0);
tft.setBrightness(255);
lv_init();
lv_disp_draw_buf_init(&draw_buf, buf, NULL, screenWidth * 10);
static lv_disp_drv_t disp_drv;
lv_disp_drv_init(&disp_drv);
disp_drv.hor_res = screenWidth;
disp_drv.ver_res = screenHeight;
disp_drv.flush_cb = my_disp_flush;
disp_drv.draw_buf = &draw_buf;
lv_disp_drv_register(&disp_drv);
drawing_screen();
bin_sem = xSemaphoreCreateBinary();
if (bin_sem == NULL) {
Serial.println("Could not create semaphore");
ESP.restart();
}
xTaskCreatePinnedToCore(lvgl_update_task,
"Task LVGL",
100000,
NULL,
1,
NULL,
1);
initDW1000();
setTimerInterrupt();
}
void setTimerInterrupt() {
timer = timerBegin(0, timer_divider, true);
timerAttachInterrupt(timer, &onTimer, true);
timerAlarmWrite(timer, timer_max_count, true);
timerAlarmEnable(timer);
}
void loop() {}
void lvgl_update_task(void *parameters) {
while (1) {
if (xSemaphoreTake(bin_sem, portMAX_DELAY) == pdTRUE) {
portENTER_CRITICAL(&mux);
lv_timer_handler();
portEXIT_CRITICAL(&mux);
}
vTaskDelay(80);
}
}
static lv_obj_t *scr;
static lv_obj_t *chart;
static lv_style_t main_black_style;
static lv_style_t title_style;
static lv_style_t text_style;
static lv_obj_t *distance_label;
static const int chartSize = screenWidth - 40;
static const int center_x = 140;
static const int center_y = 140;
static const float degree = 3.14159 / 180;
static int radius = 130;
static int angle = 0;
static volatile float projectedRange = -1;
static void draw_event_cb(lv_event_t *e) {
lv_obj_draw_part_dsc_t *dsc = lv_event_get_draw_part_dsc(e);
if (dsc->part == LV_PART_ITEMS) {
lv_obj_t *obj = lv_event_get_target(e);
lv_chart_series_t *ser = lv_chart_get_series_next(obj, NULL);
uint32_t cnt = lv_chart_get_point_count(obj);
dsc->rect_dsc->bg_opa = (LV_OPA_COVER * dsc->id) / (cnt - 1);
lv_coord_t *x_array = lv_chart_get_x_array(obj, ser);
lv_coord_t *y_array = lv_chart_get_y_array(obj, ser);
uint32_t start_point = lv_chart_get_x_start_point(obj, ser);
uint32_t p_act = (start_point + dsc->id) % cnt;
lv_opa_t x_opa = (x_array[p_act] * LV_OPA_50) / 320;
lv_opa_t y_opa = (y_array[p_act] * LV_OPA_50) / 320;
dsc->rect_dsc->bg_color = lv_color_mix(lv_color_hex(0xFFFFFF),
lv_palette_main(LV_PALETTE_GREY),
x_opa + y_opa);
}
}
static void drawRandomPoints() {
lv_chart_set_next_value2(chart, lv_chart_get_series_next(chart, NULL), lv_rand(0, chartSize), lv_rand(0, chartSize));
}
static void drawPoints() {
if (angle >= 360) {
angle = 0;
}
int x = center_x + radius * cos(-angle * degree);
int y = center_y + radius * sin(-angle * degree);
lv_chart_set_next_value2(chart, lv_chart_get_series_next(chart, NULL), lv_rand(x - 10, x + 10), lv_rand(y - 10, y + 10));
angle += 3;
}
static void add_data(lv_timer_t *timer) {
LV_UNUSED(timer);
if (projectedRange < 0) {
drawRandomPoints();
} else {
radius = map(projectedRange, 0, 5, 0, 130);
drawPoints();
}
}
static void drawing_screen(void) {
lv_style_init(&main_black_style);
lv_style_set_border_width(&main_black_style, 0);
lv_style_set_radius(&main_black_style, 0);
lv_style_set_bg_color(&main_black_style, lv_color_hex(0x000000));
//#define LV_FONT_MONTSERRAT_34 1
lv_style_init(&title_style);
lv_style_set_text_color(&title_style, lv_color_white());
lv_style_set_text_font(&title_style, &lv_font_montserrat_34);
//#define LV_FONT_MONTSERRAT_48 1
lv_style_init(&text_style);
lv_style_set_text_color(&text_style, lv_color_white());
lv_style_set_text_font(&text_style, &lv_font_montserrat_48);
scr = lv_obj_create(lv_scr_act());
lv_obj_add_style(scr, &main_black_style, 0);
lv_obj_set_size(scr, screenWidth, screenHeight);
lv_obj_t *subtitle_label = lv_label_create(scr);
lv_label_set_recolor(subtitle_label, true);
lv_label_set_text(subtitle_label, "#ffffff FINDING#");
lv_obj_t *title_label = lv_label_create(scr);
lv_label_set_text(title_label, "ESP32 Tag");
lv_obj_add_style(title_label, &title_style, 0);
lv_obj_align_to(title_label, subtitle_label, LV_ALIGN_TOP_LEFT, -2, 12);
distance_label = lv_label_create(scr);
lv_obj_add_style(distance_label, &text_style, 0);
lv_label_set_text(distance_label, "?");
lv_obj_align(distance_label, LV_ALIGN_BOTTOM_LEFT, 0, 0);
chart = lv_chart_create(scr);
lv_obj_add_style(chart, &main_black_style, 0);
lv_obj_set_size(chart, chartSize, chartSize);
lv_obj_center(chart);
lv_obj_add_event_cb(chart, draw_event_cb, LV_EVENT_DRAW_PART_BEGIN, NULL);
lv_obj_set_style_line_width(chart, 0, LV_PART_ITEMS);
lv_chart_set_type(chart, LV_CHART_TYPE_SCATTER);
lv_chart_set_div_line_count(chart, 0, 0);
lv_chart_set_range(chart, LV_CHART_AXIS_PRIMARY_X, 0, chartSize);
lv_chart_set_range(chart, LV_CHART_AXIS_PRIMARY_Y, 0, chartSize);
lv_chart_set_point_count(chart, 50);
lv_chart_series_t *ser = lv_chart_add_series(chart, lv_color_white(), LV_CHART_AXIS_PRIMARY_Y);
for (int i = 0; i < 50; i++) {
lv_chart_set_next_value2(chart, ser, lv_rand(0, chartSize), lv_rand(0, chartSize));
}
lv_timer_create(add_data, 3, chart);
}
static void updateRange(float range) {
if (range <= -1) {
projectedRange = -1;
lv_label_set_text(distance_label, "?");
} else {
projectedRange = range * 2 / 5;
//projectedRange = range;
String strDistance = String(projectedRange);
strDistance += " m";
lv_label_set_text(distance_label, String(strDistance).c_str());
}
}

View File

@@ -0,0 +1,54 @@
#include <SPI.h>
#include <DW1000.h>
#include <DW1000Ranging.h>
// connection pins
const uint8_t PIN_SCK = 18;
const uint8_t PIN_MOSI = 23;
const uint8_t PIN_MISO = 19;
const uint8_t PIN_SS = 15;
const uint8_t PIN_RST = 2;
const uint8_t PIN_IRQ = 22;
void newRange() {
Serial.print("from: ");
Serial.print(DW1000Ranging.getDistantDevice()->getShortAddress(), HEX);
Serial.print("\t Range: ");
Serial.print(DW1000Ranging.getDistantDevice()->getRange());
Serial.print(" m");
Serial.print("\t RX power: ");
Serial.print(DW1000Ranging.getDistantDevice()->getRXPower());
Serial.println(" dBm");
functionPointer(DW1000Ranging.getDistantDevice()->getRange());
}
void newDevice(DW1000Device* device) {
// Serial.print("ranging init; 1 device added ! -> ");
// Serial.print(" short:");
// Serial.println(device->getShortAddress(), HEX);
}
void inactiveDevice(DW1000Device* device) {
//Serial.print("delete inactive device: ");
//Serial.println(device->getShortAddress(), HEX);
functionPointer(-1);
}
void initDW1000() {
SPI.begin(PIN_SCK, PIN_MISO, PIN_MOSI);
//init the configuration
DW1000Ranging.initCommunication(PIN_RST, PIN_SS, PIN_IRQ); //Reset, CS, IRQ pin
//define the sketch as anchor. It will be great to dynamically change the type of module
DW1000Ranging.attachNewRange(newRange);
DW1000Ranging.attachNewDevice(newDevice);
DW1000Ranging.attachInactiveDevice(inactiveDevice);
//Enable the filter to smooth the distance
//DW1000Ranging.useRangeFilter(true);
DW1000.enableDebounceClock();
DW1000.enableLedBlinking();
DW1000.setGPIOMode(MSGP0, LED_MODE);
//we start the module as a tag
DW1000Ranging.startAsTag("7D:00:22:EA:82:60:3B:9C", DW1000.MODE_LONGDATA_RANGE_ACCURACY);
}

View File

@@ -0,0 +1,61 @@
#define LGFX_USE_V1
#include <LovyanGFX.hpp>
class LGFX : public lgfx::LGFX_Device {
lgfx::Panel_ILI9488 _panel_instance;
lgfx::Bus_SPI _bus_instance;
lgfx::Light_PWM _light_instance;
public:
LGFX(void) {
{
auto cfg = _bus_instance.config();
cfg.spi_host = VSPI_HOST;
cfg.spi_mode = 0;
cfg.freq_write = 40000000;
cfg.freq_read = 16000000;
cfg.spi_3wire = false;
cfg.use_lock = true;
cfg.dma_channel = 1;
cfg.pin_sclk = 18;
cfg.pin_mosi = 23;
cfg.pin_miso = -1;
cfg.pin_dc = 14;
_bus_instance.config(cfg);
_panel_instance.setBus(&_bus_instance);
}
{
auto cfg = _panel_instance.config();
cfg.pin_cs = 13;
cfg.pin_rst = 12;
cfg.pin_busy = -1;
cfg.memory_width = 320;
cfg.memory_height = 480;
cfg.panel_width = 320;
cfg.panel_height = 480;
cfg.offset_x = 0;
cfg.offset_y = 0;
cfg.offset_rotation = 0;
cfg.dummy_read_pixel = 8;
cfg.dummy_read_bits = 1;
cfg.readable = true;
cfg.invert = false;
cfg.rgb_order = false;
cfg.dlen_16bit = false;
cfg.bus_shared = true;
_panel_instance.config(cfg);
}
{
auto cfg = _light_instance.config();
cfg.pin_bl = 33;
cfg.invert = false;
cfg.freq = 44100;
cfg.pwm_channel = 7;
_light_instance.config(cfg);
_panel_instance.setLight(&_light_instance);
}
setPanel(&_panel_instance);
}
};
LGFX tft;