//////////////////////////////////////////////////////////////////////////////////////
////////////// © tykhon, 2019 ////////////////////////
//////////////////////////////////////////////////////////////////////////////////////
#include <SPI.h>
#include "Ucglib.h"
#include "HardwareSerial.h"
#define PMSSerial Serial2
#define SDSSerial Serial1
unsigned int SDS_Pm25;
unsigned int SDS_Pm100;
float SDS_Pm25mean;
float SDS_Pm100mean;
float SDS_Pm25f;
float SDS_Pm100f;
float PMS_Pm10mean;
float PMS_Pm25mean;
float PMS_Pm100mean;
float smoothing_factor = 0.3; // coeff for Kalman 0.01 - 0.99. Higher for less smoothing.
uint32_t start = millis();
uint32_t now = millis();
uint32_t nextrun = 0;
boolean PMSrun = false;
const int period = 180; // period of sensor poll, sec
const int sds_period = period/60;
int line_sds_25[200] = {};
int line_sds_100[200] = {};
int line_pms_10[200] = {};
int line_pms_25[200] = {};
int line_pms_100[200] = {};
byte lineIndex_pms;
byte lineIndex_sds;
unsigned int line_sds_100sum = 0;
unsigned int line_sds_25sum = 0;
Ucglib_ILI9341_18x240x320_HWSPI ucg(/*cd=*/ 16, /*cs=*/ 17, /*reset=*/ 5);
//////////////////////////////////////////////////////////////////////////
///////// SDS 011 ///////////////
//////////////////////////////////////////////////////////////////////////
void SDSworkmode(byte mode)
{
byte cs = 7 + mode;
uint8_t sleep_command[] = {0xAA, 0xB4, 0x08, 0x01, mode, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, cs, 0xAB};
// ^^ 0 for continuous, 1-30 for 1-30 min delay between turns on. ^^ checksum: 07 for 0x00, 08 for 0x01 and so on
for (uint8_t i = 0; i < 19; i++) {
SDSSerial.write(sleep_command[i]);
}
}
void SDSwakeup()
{
uint8_t wakeup_command[] = {0xAA, 0xB4, 0x06, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x06, 0xAB};
for (uint8_t i = 0; i < 19; i++) {
SDSSerial.write(wakeup_command[i]);
}
}
boolean ProcessSerialData()
{
uint8_t mData = 0;
uint8_t i = 0;
uint8_t mPkt[10] = {0};
uint8_t mCheck = 0;
while (SDSSerial.available() > 0)
{
mData = SDSSerial.read(); delay(2);//wait until packet is received
if (mData == 0xAA) //head1 ok
{
mPkt[0] = mData;
mData = SDSSerial.read();
if (mData == 0xc0) //head2 ok
{
mPkt[1] = mData;
mCheck = 0;
for (i = 0; i < 6; i++) //data recv and crc calc
{
mPkt[i + 2] = SDSSerial.read();
delay(2);
mCheck += mPkt[i + 2];
}
mPkt[8] = SDSSerial.read();
delay(1);
mPkt[9] = SDSSerial.read();
if (mCheck == mPkt[8]) //crc ok
{
SDSSerial.flush();
SDS_Pm25 = (uint16_t)mPkt[2] | (uint16_t)(mPkt[3] << 8);
SDS_Pm100 = (uint16_t)mPkt[4] | (uint16_t)(mPkt[5] << 8);
if (SDS_Pm25 > 9999)
SDS_Pm25 = 9999;
if (SDS_Pm100 > 9999)
SDS_Pm100 = 9999;
return true;
} else {Serial.println('crc not ok');};
} else {Serial.println('head not ok');};
}
}
}
//////////////////////////////////////////////////////////////////////////
///////// PMSA003 ///////////////
//////////////////////////////////////////////////////////////////////////
void PMSworkmode(byte mode)
{
byte cs = 70 + mode;
uint8_t mode_command[] = {0x42, 0x4D, 0xE1, 0x00, mode, 0x01, cs};
// ^^ 0 for passive, 1 for active. The last byte - checksum: 70 for 0x00, 71 for 0x01 and so on
for (uint8_t i = 0; i < 7; i++) {
PMSSerial.write(mode_command[i]);
}
delay(100);
}
void PMSwakeup()
{
uint8_t wakeup_command[] = {0x42, 0x4D, 0xE4, 0x00, 0x01, 0x01, 0x74};
for (uint8_t i = 0; i < 7; i++) {
PMSSerial.write(wakeup_command[i]);
}
delay(100);
}
void PMSsleep()
{
uint8_t sleep_command[] = {0x42, 0x4D, 0xE4, 0x00, 0x00, 0x01, 0x73};
for (uint8_t i = 0; i < 7; i++) {
PMSSerial.write(sleep_command[i]);
}
delay(100);
}
void PMSpassive_mode_read()
{
uint8_t read_command[] = {0x42, 0x4D, 0xE2, 0x00, 0x00, 0x01, 0x71};
for (uint8_t i = 0; i < 7; i++) {
PMSSerial.write(read_command[i]);
}
delay(100);
}
///////////////////////////////////////////////////////////////////
struct pms5003data {
uint16_t framelen;
uint16_t pm10_standard, pm25_standard, pm100_standard;
uint16_t pm10_env, pm25_env, pm100_env;
uint16_t particles_03um, particles_05um, particles_10um, particles_25um, particles_50um, particles_100um;
uint16_t unused;
uint16_t checksum;
};
struct pms5003data data;
boolean readPMSdata(Stream *s) {
if (! s->available()) {
Serial.println("data not available");
return false;
}
// Read a byte at a time until we get to the special '0x42' start-byte
if (s->peek() != 0x42) {
s->read();
Serial.println("no 42");
return false;
}
// Now read all 32 bytes
if (s->available() < 32) {
Serial.println("less than 32");
return false;
}
uint8_t buffer[32];
uint16_t sum = 0;
s->readBytes(buffer, 32);
// get checksum ready
for (uint8_t i=0; i<30; i++) {
sum += buffer[i];
}
/* debugging
Serial.println();
for (uint8_t i=0; i<32; i++) {
// was i=2
Serial.print("0x"); Serial.print(buffer[i], HEX); Serial.print(", ");
}
Serial.println();
*/
// The data comes in endian'd, this solves it so it works on all platforms
uint16_t buffer_u16[15];
for (uint8_t i=0; i<15; i++) {
buffer_u16[i] = buffer[2 + i*2 + 1];
buffer_u16[i] += (buffer[2 + i*2] << 8);
}
// put it into a nice struct :)
memcpy((void *)&data, (void *)buffer_u16, 30);
while (s->available()) {s->read();};
if (sum != data.checksum) {
Serial.println("Checksum failure");
Serial.print(" sum = ");
Serial.print(sum, HEX);
Serial.print(" data.checksum = ");
Serial.println(data.checksum, HEX);
return false;
}
// success!
return true;
}
//////////////////////////////////////////////////////////////////////////////////
void math_PMS(){
if (!PMS_Pm10mean) PMS_Pm10mean = data.pm10_standard;
if (!PMS_Pm25mean) PMS_Pm25mean = data.pm25_standard;
if (!PMS_Pm100mean) PMS_Pm100mean = data.pm100_standard;
PMS_Pm10mean = PMS_Pm10mean - smoothing_factor*(PMS_Pm10mean - data.pm10_standard);
PMS_Pm25mean = PMS_Pm25mean - smoothing_factor*(PMS_Pm25mean - data.pm25_standard);
PMS_Pm100mean = PMS_Pm100mean - smoothing_factor*(PMS_Pm100mean - data.pm100_standard);
line_pms_10[lineIndex_pms] = int(PMS_Pm10mean*10.0);
line_pms_25[lineIndex_pms] = int(PMS_Pm25mean*10.0);
line_pms_100[lineIndex_pms] = int(PMS_Pm100mean*10.0);
lineIndex_pms++;
if (lineIndex_pms >= sizeof(line_pms_100)/sizeof(int)) {lineIndex_pms = 0;};
}
void math_SDS(){
if (!SDS_Pm25mean) SDS_Pm25mean = SDS_Pm25/10.0;
SDS_Pm25mean = SDS_Pm25mean - smoothing_factor*(SDS_Pm25mean - SDS_Pm25/10.0);
if (!SDS_Pm100mean) SDS_Pm100mean = SDS_Pm100/10.0;
SDS_Pm100mean = SDS_Pm100mean - smoothing_factor*(SDS_Pm100mean - SDS_Pm100/10.0);
line_sds_25[lineIndex_sds] = int(SDS_Pm25mean*10.0);
line_sds_100[lineIndex_sds] = int(SDS_Pm100mean*10.0);
lineIndex_sds++;
if (lineIndex_sds >= sizeof(line_sds_100)/sizeof(int)) {lineIndex_sds = 0;};
}
//////////////////////////////////////////////////////////////////////////////////////
///////////////////////////// graph ///////////////////////////////
//////////////////////////////////////////////////////////////////////////////////////
void main_graph_sds(){
ucg.setColor(0, 0, 0); // clear field
ucg.drawBox(1, 1, 220, 119);
ucg.setColor(255, 255, 255); // half line
ucg.drawHLine(0, (ucg.getHeight()/2), ucg.getWidth());
ucg.setColor(250, 255, 10);
ucg.drawVLine(20, 5, 90); // y line
ucg.drawHLine(20, 95, 200); // x line
int maxvalue = 1; // y scale
for (int i = 0; i < (sizeof(line_sds_100)/sizeof(int)); i++){
maxvalue = max(maxvalue, line_sds_100[i]);
maxvalue = max(maxvalue, line_sds_25[i]);
};
maxvalue = int(ceil(float(maxvalue)/50.0)*50);
ucg.setFont(ucg_font_helvB12_hr);
ucg.setColor(255,255,255);
ucg.setPrintPos(1,20);
ucg.print(maxvalue/10);
int hours_count = sizeof(line_sds_100)/sizeof(int); // x scale
int step_in_min = sds_period;
hours_count = hours_count * step_in_min;
hours_count = hours_count / (-60);
int onestep = 1;
if (hours_count < -5) {onestep = 2;};
for (int i = 0; i >= hours_count; i = i - onestep) {
int posx = 20 +(sizeof(line_sds_100)/sizeof(int)) + i*(60/step_in_min);
ucg.setColor(250,255,10);
ucg.drawVLine(posx, 95, 5);
int shift = posx+1;
if (shift > 200) {shift = shift-10;};
ucg.setPrintPos(shift, 114);
ucg.setColor(255,255,255);
ucg.print(i);
};
int g = 20+(sizeof(line_sds_100)/sizeof(int)); // plot draw
for (int i = lineIndex_sds-1; i >= 0; i--){
int x1 = g;
g--;
int y1 = map(line_sds_100[i], 0, maxvalue, 0, 92);
int y2 = map(line_sds_25[i], 0, maxvalue, 0, 92);
ucg.setColor(10, 80, 250);
ucg.drawVLine(x1, 95-y1, y1);
ucg.setColor(250, 10, 80);
ucg.drawVLine(x1, 95-y2, y2);
};
for (int i = (sizeof(line_sds_100)/sizeof(int))-1; i >= lineIndex_sds; i--){
int x1 = g;
g--;
int y1 = map(line_sds_100[i], 0, maxvalue, 0, 92);
int y2 = map(line_sds_25[i], 0, maxvalue, 0, 92);
ucg.setColor(10, 80, 250);
ucg.drawVLine(x1, 95-y1, y1);
ucg.setColor(250, 10, 80);
ucg.drawVLine(x1, 95-y2, y2);
};
}
void main_graph_pms(){
ucg.setColor(0, 0, 0); // clear field
ucg.drawBox(1, 124, 220, 119);
ucg.setColor(255, 255, 255); // half line
ucg.drawHLine(0, (ucg.getHeight()/2), ucg.getWidth());
ucg.setColor(250, 255, 10);
ucg.drawVLine(20, 128, 90); // y line
ucg.drawHLine(20, 218, 200); // x line
int maxvalue = 1; // y scale
for (int i = 0; i < (sizeof(line_pms_100)/sizeof(int)); i++){
maxvalue = max(maxvalue, line_pms_100[i]);
maxvalue = max(maxvalue, line_pms_25[i]);
maxvalue = max(maxvalue, line_pms_10[i]);
};
maxvalue = int(ceil(float(maxvalue)/50.0)*50);
ucg.setFont(ucg_font_helvB12_hr);
ucg.setColor(255,255,255);
ucg.setPrintPos(1,143);
ucg.print(maxvalue/10);
int hours_count = sizeof(line_pms_100)/sizeof(int);
int step_in_min = sds_period;
hours_count = hours_count * step_in_min;
hours_count = hours_count / (-60);
int onestep = 1;
if (hours_count < -5) {onestep = 2;};
for (int i = 0; i >= hours_count; i = i - onestep) {
int posx = 20 +(sizeof(line_pms_100)/sizeof(int)) + i*(60/step_in_min);
ucg.setColor(250,255,10);
ucg.drawVLine(posx, 218, 5);
int shift = posx+1;
if (shift > 200) {shift = shift-10;};
ucg.setPrintPos(shift, 237);
ucg.setColor(255,255,255);
ucg.print(i);
};
int g = 20+(sizeof(line_pms_100)/sizeof(int)); // plot draw
for (int i = lineIndex_pms-1; i >= 0; i--){
int x = g;
g--;
int y1 = map(line_pms_100[i], 0, maxvalue, 0, 92);
int y2 = map(line_pms_25[i], 0, maxvalue, 0, 92);
int y3 = map(line_pms_10[i], 0, maxvalue, 0, 92);
ucg.setColor(10, 80, 250);
ucg.drawVLine(x, 218-y1, y1);
ucg.setColor(250, 10, 80);
ucg.drawVLine(x, 218-y2, y2);
ucg.setColor(80, 250, 10);
ucg.drawVLine(x, 218-y3, y3);
};
for (int i = (sizeof(line_pms_100)/sizeof(int))-1; i >= lineIndex_pms; i--){
int x = g;
g--;
int y1 = map(line_pms_100[i], 0, maxvalue, 0, 92);
int y2 = map(line_pms_25[i], 0, maxvalue, 0, 92);
int y3 = map(line_pms_10[i], 0, maxvalue, 0, 92);
ucg.setColor(10, 80, 250);
ucg.drawVLine(x, 218-y1, y1);
ucg.setColor(250, 10, 80);
ucg.drawVLine(x, 218-y2, y2);
ucg.setColor(80, 250, 10);
ucg.drawVLine(x, 218-y3, y3);
};
}
////////////////////////////////////////////////////////////////////////////
void print_SDS(){
SDS_Pm25f = SDS_Pm25/10.0;
SDS_Pm100f = SDS_Pm100/10.0;
String dataString = "SDS_2.5:\t"+String(SDS_Pm25f,0)+"\tSDS_10:\t"+String(SDS_Pm100f,0)+"\tSDS_2.5~:\t"+String(SDS_Pm25mean,1)+"\tSDS_10~:\t"+String(SDS_Pm100mean,1);
dataString.replace(".",",");
Serial.print(dataString);
}
void print_PMS(){
/*
Serial.print("\tPMS_1:\t"); Serial.print(data.pm10_standard);
Serial.print("\tPMS_2.5:\t"); Serial.print(data.pm25_standard);
Serial.print("\tPMS_10:\t"); Serial.print(data.pm100_standard);
Serial.print("\tPMS_1~:\t"); Serial.print(PMS_Pm10mean,1);
Serial.print("\tPMS_2.5~:\t"); Serial.print(PMS_Pm25mean,1);
Serial.print("\tPMS_10~:\t"); Serial.println(PMS_Pm100mean,1);
*/
String dataString = "\tPMS_1:\t"+String(data.pm10_standard)+"\tPMS_2.5:\t"+String(data.pm25_standard)+"\tPMS_10:\t"+String(data.pm100_standard)+"\tPMS_1~:\t"+String(PMS_Pm10mean,1)+"\tPMS_2.5~:\t"+String(PMS_Pm25mean,1)+"\tPMS_10~:\t"+String(PMS_Pm100mean,1);
dataString.replace(".",",");
Serial.println(dataString);
}
void print_PMS_full(){
Serial.println();
Serial.println("---------------------------------------");
Serial.println("Concentration Units (standard)");
Serial.print("PM 1.0: "); Serial.print(data.pm10_standard);
Serial.print("\t\tPM 2.5: "); Serial.print(data.pm25_standard);
Serial.print("\t\tPM 10: "); Serial.println(data.pm100_standard);
Serial.println("---------------------------------------");
Serial.println("Concentration Units (environmental)");
Serial.print("PM 1.0: "); Serial.print(data.pm10_env);
Serial.print("\t\tPM 2.5: "); Serial.print(data.pm25_env);
Serial.print("\t\tPM 10: "); Serial.println(data.pm100_env);
Serial.println("---------------------------------------");
Serial.print("Particles > 0.3um / 0.1L air:"); Serial.println(data.particles_03um);
Serial.print("Particles > 0.5um / 0.1L air:"); Serial.println(data.particles_05um);
Serial.print("Particles > 1.0um / 0.1L air:"); Serial.println(data.particles_10um);
Serial.print("Particles > 2.5um / 0.1L air:"); Serial.println(data.particles_25um);
Serial.print("Particles > 5.0um / 0.1L air:"); Serial.println(data.particles_50um);
Serial.print("Particles > 10.0 um / 0.1L air:"); Serial.println(data.particles_100um);
Serial.println("---------------------------------------");
}
void lcd_print(){
ucg.setColor(0, 0, 0);
ucg.drawBox(270, 0, 80, 119);
ucg.drawBox(270, 121, 80, 240);
ucg.setFont(ucg_font_fub20_hf);
ucg.setColor(255, 255, 255);
ucg.setPrintPos(270,35);
ucg.print(SDS_Pm100f,0);
ucg.setPrintPos(270,90);
ucg.print(SDS_Pm25f,0);
ucg.setPrintPos(270,160);
ucg.print(data.pm100_standard);
ucg.setPrintPos(270,195);
ucg.print(data.pm25_standard);
ucg.setPrintPos(270,230);
ucg.print(data.pm10_standard);
}
void setup() {
Serial.begin(115200);
PMSSerial.begin(9600, SERIAL_8N1, 32, 33);
SDSSerial.begin(9600, SERIAL_8N1, 34, 35);
SDSwakeup();
delay(10);
SDSwakeup();
SDSworkmode(sds_period);
PMSwakeup();
PMSworkmode(0);
PMSwakeup();
ucg.begin(UCG_FONT_MODE_SOLID);
ucg.clearScreen();
ucg.setRotate270();
ucg.setFont(ucg_font_fub14_hf);
ucg.setColor(255, 255, 155);
ucg.setPrintPos(234,35);
ucg.print("10");
ucg.setPrintPos(234,90);
ucg.print("2.5");
ucg.setPrintPos(234,160);
ucg.print("10");
ucg.setPrintPos(234,195);
ucg.print("2.5");
ucg.setPrintPos(234,228);
ucg.print("1.0");
}
void loop() {
now = millis();
if ((now > nextrun)&(!PMSrun)) {
PMSwakeup();
PMSrun = true;
}
if (now > (nextrun + 30000)) {
if (ProcessSerialData()){
math_SDS();
print_SDS();
};
while (PMSSerial.available()) { PMSSerial.read(); };
PMSpassive_mode_read();
delay(1000);
if (readPMSdata(&PMSSerial)) {
math_PMS();
print_PMS();
};
PMSsleep();
PMSrun = false;
lcd_print();
main_graph_sds();
main_graph_pms();
nextrun = now + period*1000 - 30000;
};
delay(10);
}
Одна ESP32 стоит в районе 4$
aliexpress.com/item/32928267626.html
PS. Датчика температуры там нет, его выпилили в поздних версиях.
А h серия имеет конский ценник
Просто коммент что кит на основе stm32 интереснее звучит странно
Тем более что документациия на esp открыта
Кроме того, далеко не в каждой поделке нужен stm32 ;) Тут вот ниже за атмегу топят)
-реально необходимая физическая мощность (сюда я включаю объёмы памяти, частоту камня, наборы поддерживаемых инструкций, интерфейсы и т.п.)
-привычки и личных предпочтений (если не планируется массовый выпуск устройства, то на разницу в стоимости можно и не обращать внимания в некоторых случаях, особенно если привык к какой-то платформе и лень смотреть, как с другой работать).
Если же речь идёт о чём-то тиражируемом, чему достаточно мощности атмеги, то ясен пень — разница в цене, помноженная на объём, будет очень ощутимой.
Или STM32F103CBT6 за доллар.
А теперь сравните цены на атмеги.
И сравним время когда у вас и там и там замигает ws2812b
На атмегу за 3 минуты скачивается либа и правится только пин.
А под стм32 либ с свободном доступе не так и много и они часто не работают без правок
1. Arduino (ATmega328P) реально раза в три дешевле
2. Есть огромное количество проектов, для которого ресурсов Arduino более чем достаточно (количество ног, объём RAM и ROM, скорость работы, потребляемая энергия)
3. Arduino плата значительно компактнее. Что часто имеет весьма важное значение.
4. ESP32 во много раз прожорливее Arduino. Требования по питанию для ESP32 гораздо серьёзнее. Кроме того, требуется гораздо более высокий уровень программирования для ESP32, чтобы заставить ESP32 бережливее расходовать энергию.
5. У Arduino выводы не обязательно 5v. Есть версия с выводами и 3.3v.
6. Arduino ГОРАЗДО более дружественна по аппаратной части. Для Arduino совершенно не обязательно притягивать к земле не используемые ноги. Arduino реально практические не боится статики и даже низковольтная версия поддерживает гораздо более высокие напряжения без последствий. В общем, ATmega328P по надёжности это практически как автомат Калашникова. А вот всякие ESP8266, ESP32, STM32 часто глючат, дохнут и вообще гораздо более нежные девайсы.
7. Готовых библиотек для ESP32 мало. Если кто-то планируется на ESP32 цеплять какие-то устройства, то нужно сразу готовиться к тому, что для ESP32 придётся для многих внешних устройств писать самостоятельно драйвер/библиотеку. Это, на самом деле, не так уж и сложно. Но это точно требует гораздо более высокий уровень знаний.
В общем для меня вывод один. Автор обзора не слишком хорошо разбирается в программировании, и считает, что чем оптимизировать программу проще купить более мощный компьютер.
А вообще нормальный LDO линейник реально потребляем где-то 0.5mA и меньше. Но никак не 7mA.
Конечно, сделать микро-потребление — непростая задача, но не всегда оно и нужно. Чтобы измерять раз в 15 минут температуру на улице, достаточно Ардуино. А esp — это все-таки для более сложных задач. У меня вот она экраном рулит, два датчика вентиляторами крутят. Тут уж не важно, сколько там esp потребляет.
А то у 328й слишком мало ног, чтоб управлять 6 разрядным, 7 сегментным LED дисплеем.
Quiescent Current AMS1117-3.3 5-11 mA,
PS Выбор контроллера, я считаю, во многом определеется привычкой. Архитектуре AVR уже четверть века. Несомненным преимуществом контроллеров ATmega является проста, существует огромное кол-во обучающего материала, порог вхождения достаточно низкий. А использование абстракций платформы Arduino опускает его практически на детский уровень (в буквальном смысле дети могут писать программы).
STM32 и ESP это чипы другого поколения: более сложные но и более мощные и гибкие, но их уже нужно «уметь правильно готовить». (в этом плане, Arduino, в обмен на простоту, обычно приносит в жертву гибкость и оптимальность решений.) Это конечно не повод вычёркивать ATmeg-и из своих проектов, очень много простых задач, которые успешно ими решаются.
С Arduino, я считаю, можно стартовать, но если тема программирования МК «зацепила», засиживаться на этой платформе не стоит.
Насчёт гибкости утверждение ну очень спорное.
m.habr.com/ru/post/404075/
И у друга такие же часы работают
Вы хоть представляете какой тираж у esp8266?
Почти все умные розетки на этом чипе
Проблема ST-Link давным давно известна и уже много лет как решена, для сложных условий эксплуатации производитель настоятельно рекомендует использовать ISOL версию.
Может нужно дома что то изменить? а не валить на контроллер, и учиться работать с микропроцессорной техникой. Я за свои 25+ работой с электроникой не припомню, что бы что то статикой прибил.
Например rtt.
Кроме того jlink подходит для многих микроконтроллеров
хотя я в итоге на пилюле заменил проц на 072 — уж больно удобно с уартом в одном флаконе…
там все защиты есть и софтом он опознается и обновляется
зачем что-то напаивать на китайский ст линк, если можно купить нормальный 1 раз
Я видел как они меж сеткой эл проводов под током гуляют обходя их и не зацепив ни один!
Хотя заметил, что от прикосновения к проводу может зависнуть. Возможно та самая статика влият. Но для радио это не критично, лишь бы не сгорело.
Ну, и современные игры гораздо более сложные технически, чем предшественники, программистам есть чем заняться кроме оптимизаций.
Это чисто рыночная «фишка»: то, что дешевле — то и уходит в массы.
Дешевле купить 8-ядерный комп, чем оплачивать работу квалифицированного программиста.
Дешевле плодить бесконечные ремейки франшиз, чем творить новые шедевры — кино, песни.
Дешевле замутить тортик из пальмового масла — пусть полгода на прилавке стоит.
И т.д.
но при заказе от 2х штук с али выгоднее будет
Но я толком ничего сам не программировал, все по инструкциям.
Как быстрее что посчитать тут уж самому решать
Не занудствую, просто глаз зацепился… )))
За обзор — спасибо! Присмотрюсь получше. Нужно будет поискать реализацию на ней поделок для Apple Home Kit. Для предыдущей ESP 8266 давно есть.
У меня «трудятся» кастомные пошивки для Sonoff-а в HomeKit отсюда.
Не занудство, просто глаз зацепился. :)
А ещё О2 и водорода. И быстродействие жизненно необходимо.
А на ардуино производительности уже даже для паяльника не хватает для отработки формул.На лодке им делать нечего-утонет.
А теперь поймите и простите меня.
Кстати, вы уверены, что там присутствует датчик Холла (измерение магнитного поля)? Какой смысл в его существовании там, или просто, до кучи напихали, а дальше сами -всё сами?
Ведь они везде бывают
По крайней мере я такие устройства не разрабатывал и вряд ли хочу)
И это при том, что все поняли, речь о ядре АРМ в его бесчисленных исполнениях
void foo (uint8_t *ptr) {
*ptr =;
}
int32_t var;
foo ((uint8_t *)&var + 1);
И на М4 все пройдет на ура, а на M0 — hard fault
И такой код очень часто приходится писать в условиях сетевых протоколов побайтовых и т д.
А стеки задач для, например UCOS — надо выравнивать по 8 байтовой границе, и это тоже особенность архитектуры.И это надо знать, если претендуешь на что-то, особенно давать советы и говорить куда смотреть
Эта особенность свойственна некоторым архитектурам от ARM Holdings, причём не только микроконтроллерным, но и «взрослым».
Такое, кстати, было и у легендарного DEC Alpha.
Google: «Unaligned Memory Access».
ru.aliexpress.com/i/32868241470.html
ru.aliexpress.com/i/32982100489.html
Это как? :)
Я про Atom + PlatformIO. Работает быстро, подсветка кода, автообновление библиотек со своим пакетным менеджером, подсказки, прошивает огромное количество микроконтроллеров, есть дебаг (нужно купить отдельную плату для ESP32).
но вообще да, поражает, вроде есть интернет, куча людей занимается, а всё равно мается с этим дефолтным текстовым редактором
Замаялся я уже по инклюдам елозить.
Эклипс показывает какие то моменты, но не наглядно. И idf не учитывает. Или настроить надо?
Интересует именно прошаренный текстовый редактор.
В качестве сборщика/компилятора мне и msys'a хватает
я пробовал для стм32 и получлось очень не в сторону стм32
компилятор же показывает эти проценты
Сам не в состоянии сделать, убил кучу времени, так и не разобрался :( из железа ( ардуино нано, два датчика ds18b20, микросхема часов ds3231, дисплей oled 1.3, маленькая плата понижающая напряжение).
Буду безумно благодарен, если кто то откликнется, более детально расскажу, что я бы хотел реализовать
+
youtu.be/9D9381jkZrw
= ваш проект
при помощи этого реализуется за 5 минут без строчки кода
насчет олед не знаю, вроде на форуме кто-то делал модули под разные индикаторы
Это замена штатных часов, которые не удается восстановить. Купленный экран замечательно подходит вместо штатных. Я же Вас не заставляю помогать.
Кстати, сейчас удобно несложные вещи через Xod программировать, порог вхождения низкий и результат наглядно видно+отладка.
www.layoutit.com/cn
pingendo.com/
mobirise.com/bootstrap-builder/
P.S. Ваш код какой-то тяжелый, не осилил и 10-ой части (
«Фара́д (русское обозначение: Ф; международное обозначение: F; прежнее название — фара́да) — единица измерения электрической ёмкости в Международной системе единиц (СИ), названная в честь английского физика Майкла Фарадея[1].»
ULP coprocessor programming
Programming ULP coprocessor using C macros
Согласно даташиту, потребление в deep sleep без сопроцессора 10 мкА, с работающим сопроцессором — 150 мкА. Использовать сопроцессор без deep sleep особого смысла нет.
2. Мне понравилось как ребята делали генерацию звука на ESP32. Z не знаю на чем еще малогабаритном сделать такое с поддержкой BT и WiFi…
Автору отдельный плюс за юмор: ...;-)
Если обнаружите решение, то обязательно напишите тут.
Да, и css811 у меня показывал в основном погоду на марсе. Очухивался только если на него чем-то уж совсем химическим дунуть. Тогда мигом зашкаливал. А так — то потихоньку вверх уплывет. Перегрузишь — снова все чисто. То зависнет на одних показателях. Мутный датчик.
Здесь больше ног модуля выведено на штырьки — 38, а у автора — 32.
есть много полезного по измерению качества воздуха.
Вы не ошиблись? Ведь ams1117 — линейный стабилизатор, да и дросселя на плате нет…