Pull to refresh
4
0
Send message

Когда вы создаёте список, используя генераторное выражение, вы создаёте также итератор:

Я бы был аккуратнее, потому что есть ещё вот такая конструкция (круглые скобки):

myList = (x * x for x in range(3))

И вот это как раз я бы назвал генераторным выражением. Как минимум, я бы добавлял в скобках оригинальное название терминов, которые трудно переводятся (в данном случае это list comprehension).

Всё, к чему можно применить конструкцию «for… in...», является итерируемым объектом:

А зачем вы переводите так, что каждый раз у вас новый термин ? В оригинале заголовок Iterables - вы его перевели как Итераторы . Тут то же слово в оригинале, но теперь он у вас итерируемый объект .

Ваш код будет вызываться каждый раз, когда for обращается к генератору.

Вводит в заблуждение. Оригинал: "Then, your code will continue from where it left off each time for uses the generator." - Каждый раз, когда for обращается к генератору на очередной итерации, ваша функция продолжит с того места, где она была прервана на предыдущей итерации. Как-то так.

Этот код содержит несколько меньших частей:

Там "smart parts", а не "small parts".

Цикл итерируется по списку, но списко расширяется во время итерации :-) Это лаконичный способ обойти все сгрупиррованные данные, зоть это и немного опасно, так как может обернуться бесконечным циклом. В таком случае

Тут вообще с точностью до наоборот. Не в таком случае, а в этом (имеется в виду случай, описанный в коде). А у вас тут как будто вы дальше продолжаете обосновывать предыдущее утверждение про опасность бесконечного цикла. Хотя автор просто описывает дальше, как код работает.

который ожидает на вход что-нибудь итерируемое и добавляет его значения к списку.

Теперь iterable превратилось в что-нибудь итерируемое.

Дальше уже не стал корректировать.

Перевод на троечку. Лучше прочтите оригинал.

Как это нет, вроде как раз есть. Каждый раз candidates модифицируются ссылками на узлы, при вызове extend. То, что каждый раз выкусывается самый ранний делу не помогает. Или я что-то не понял.

На мой вгляд здесь действительно есть место введению в заблуждение. extend как раз-таки добавит ссыли на узлы. Генератор тут вообще ничего не оптимизирует. То же самое можно было сделать с обычными ссылками. Либо я что-то тоже не понимаю.

Приветствую ! Спасибо за статью. Тоже недавно приобрел такой сенсор. Буду смотреть. А пока:

Динамическое добавление насосов в класс контроллера. Для добавления насоса в контроллер надо добавить строку:

С одной стороны динамическое. С другой --- нужно модифицировать прошивку и перешивать.

с классами SoilSensor, PumpController, ProcessStats и Pump,

NIT. Форматирование не везде.

на микроконтроллерах Arduino

NIT. ИМХО здесь лучше использовать слово платформа (которое вы как раз далее используете).

// Буфер для форматированной строки
char buffer[100];

Захардкоженное значение. Я бы использовал:

constexpr uint8_t gBufferSize = 100;
char buffer[gBufferSize];

Но вообще я предпочитаю конфигурацию хранить в отдельном файле. Типа config.h . Так скетч не захламляется.

// Инвертированные значения HIGH и LOW
const int MYHIGH = LOW;
const int MYLOW = HIGH;

Тут уже сказали про это. Имя плохое. Более того, int здесь избыточен может быть. Достаточно uint8_t , хотя надо смотреть, что там по памяти будет. В любом случае, всякие digitalWrite uint8_t ожидают, ЕМНИП.

unsigned long minTime = 0xFFFFFFFF; // Максимальное значение unsigned long

Я бы поглядел в limits.h : тут . Т.е.

#include <limits.h>

...

unsigned long minTime = ULONG_MAX;

// А ещё лучше

typedef unsigned long ms_t; // Или time_t

...

ms_t minTime = ULONG_MAX;
// Метод для добавления насоса
  bool addPump(SoilSensor sensor, int pumpPin, unsigned long pumpDuration) {

Я бы ещё добавил проверку на пересечение. Т.е. что будет, если я пытаюсь добавить насос на занятый пин ? С другой стороны, ниже в setup я не вижу проверки статуса добавления.

// Класс контроллера насосов
class PumpController {
private:
  Pump** pumps;           // Массив указателей на насосы

Как альтернатива, можно использовать шаблоны, и сделать класс

template <uint8_t N = 10>
class PumpController {
  private:
    Pump*[N] = {}; // ЕМНИП тут уже нулевые указатели, но проверьте

  public:
    static constexpr MaxN = N; // если надо
}
 // Инициализация последовательного порта
  Serial.begin(9600);

Зачем такая низкая скорость ? Не, я понимаю, что тут, наверное, не бутылочное горлышко, но подозреваю, что это сделано, потому что в тутриалах так.

 // Добавление насосов в контроллер
  pumpController.addPump(SoilSensor(A0, 800, 100000), 2, 2000);  // Насос 1
  pumpController.addPump(SoilSensor(A1, 275, 16000), 3, 2000);   // Насос 2
  pumpController.addPump(SoilSensor(A2, 600, 700000), 4, 2000);  // Насос 3
  pumpController.addPump(SoilSensor(A3, 700, 7000000), 5, 2000);  // Насос 4

Как я уже сказал выше: не вижу проверку статуса добавления. И так, просто мысли вслух: я вижу тут проблему, что сенсоры приколочены к контроллеру. Т.е., если мне надо сенсор, ещё как-то использовать, то я этого сделать не могу, потому что он только внутри контроллера существует. Может быть, лучше было сделать так:

Pump::Pump(const SoilSensor* sensor);
// и
bool PumpController::addPump(const Pump* pump);

И тупо в скетче (скорее всего где-то вру, но набросок) :

SoilSensor(A0, 800, 100000) sAloe;
SoilSensor(A1, 275, 16000) sLemon;
SoilSensor(A2, 600, 700000) sCactus;

Pump pAloe(&sAloe);
Pump pLemon(&sLemon);
Pump pCactus(&sCactus);

PumpController p;
p.addPump(&pAloe);
p.addPump(&sLemon);
p.addCactus(&pCactus);

На мой взгляд так выглядит нагляднее. И возникает возможность использовать один насос на несколько датчиков, если нужно.

P.S. Вот такой тред есть:
https://www.reddit.com/r/arduino/comments/q1anwt/beware_of_faulty_capacitive_soil_moisture_sensors/

P.P.S. А почему > для цитирования не работает ?


Вклинюсь.

Недавно делал реализацию FSM на C++. Состояния (State) и События (Event) представлены enum 'ами. Переходы (Transition) --- это мапы типа [EState, EEvent] -> EState, т.е. текущее состояние и событие определяет конечное. Далее у FSM есть методы void process(EEvent) и bool step() . Первый --- ищет в вышеупомянутом мапе переходов соответствующую пару события и текущего состояния и меняет текущее состояние. Второй --- делает действие, соответствующее текущему состоянию. Т.е. выглядит это следующим образом:

FSM fsm; // A bit more complicated but doesn't matter now
EEvent event;

while(fsm.step()) {
  //get event somehow
  event = ...;
  fsm.process(event);
}

В этом смысле гарантии на уровне того самого списка переходов. Далее можно навешивать тесты и/или валидации. Скажем, что нет переписывающих переходов, т.е., когда сначала [A, B] -> C, а потом [A, B] -> D. И т.д. Я даже видел реализацию чисто на шаблонах. Статья даже на хабре есть.

Спасибо. Я тоже ламинатор взял FGK-320S. Фоторезист китайский беру AQUA MER ME720. Получается неплохо.

Не совсем понял. В начале вы говорите так, что подразумевается какая-то неоднозначность справедливости позиции автора статьи. Но дальше я не вижу никакого противопоставления. Вы просто говорите, что данные окна удобно хранить в классе, но про методы ничего не сказали. Они тоже у окна удобнее, или это отдельные функции ?

Я теперь так и делаю. Пушка вообще. Даже старым станком советским я тепепь делаю отверстия 0.9мм

Скрытый текст
# Устанавливаем соединение с базой данных
with sqlite3.connect('my_database.db') as connection:
    cursor = connection.cursor()

    try:
        # Начинаем транзакцию автоматически
        with connection:

Извините, не совсем уверен, что тут повторный context manager нужен. Вы же уже и так в контекст вошли в первой строчке. Более того, необходимо выставить autocommit = False при соединении. Иначе контекст ничего не делает: docs

UPD: Пардон, насчет последнего я ошибся. Документация говорит, что в случае, если autocommit = LEGACY_TRANSACTION_CONTROL (что по умолчанию так), то поведение диктуется другим параметром, а именно, isolation_level . И по умолчанию, действительно, транзакции открываются перед некоторыми операциями над базой. Но, на мой взгляд, это сильно всё запутывает, а "explicit better than implicit". Вот этот пост довольно полезный: SE

Айнштайн. Ойлер. Фройд. Ну это так, навскидку. Как написали ниже, если уж называть правильно, то надо называть на "родном языке". Считаю, что это абсолютно не важно. Любая русификация будет неправильной в узком смысле. Я не пытаюсь проявить таким образом неуважение. Просто я об этом не задумываюсь и вам не советую. В моих кругах он известен как линус.

А почему ошибка ? Напряжение на резисторе/конденсаторе пропорционально интегралу от входного напряжения.

https://youtu.be/S5S9LIT-hdc?si=zfQP4UgN8M_lTA9r

Скрытый текст

Линус Торвальдс печатает двумя пальцами

Как же плохо... прям не заморачиваются. Уже и Autodesc туда же --- на стартовой странице сгенеренная печатная плата.

Да, я, к сожалению, знаю :) Не додумался до такого простого решения. Теперь только так делать буду. Бонусом меньше вероятность пятак сорвать сверлом. Спасибо !

А точки у пятачков меди -- это чтобы их протравить и затем высверлить ?

У меня мысли следующие. Оператор производной --- действует на функцию (а не на число) и возвращает функцию, а не число. Что в данном случае означает запись 2' ? Я понимаю, что есть функции-константы, и да --- для таких функций будем иметь f' = 0. Но меня корёжит запись 2' .

Information

Rating
Does not participate
Registered
Activity