mafell_broschuere_nfu50_0220_rus_s.pdf
1.2 MB
Инструкция и рекламный буклет пазового фрезера Mafell NFU 50 ✅
Интерьерная лофт-лампа «Вектор» ручной работы.
Тёплое дерево + холодный металл.
Высота 46 см, основание треугольное со стороной 33 см, винтажная лампочка в комплекте.
Каждая деталь сделана вручную. Дерево покрыто маслом «Орех».
Такой вещи нет в магазинах.
Простая сборка.
Срок изготовления — от 3 дней.
Доставка транспортными компаниями Почта России/СДЭК (оплачивается отдельно)
Цена 3790р
(каждая лампа уникальна — рисунок дерева не повторяется)
Тёплое дерево + холодный металл.
Высота 46 см, основание треугольное со стороной 33 см, винтажная лампочка в комплекте.
Каждая деталь сделана вручную. Дерево покрыто маслом «Орех».
Такой вещи нет в магазинах.
Простая сборка.
Срок изготовления — от 3 дней.
Доставка транспортными компаниями Почта России/СДЭК (оплачивается отдельно)
Цена 3790р
(каждая лампа уникальна — рисунок дерева не повторяется)
🔧 УМНАЯ ДРЕЛЬ НА ARDUINO NANO — ПОЛНЫЙ ПРОЕКТ
Собрал электронный уровень для шуруповёрта своими руками. Показывает наклон по двум осям, при попадании в ноль загорается «РОВНО» и пищит зуммер. Калибровка — одним нажатием кнопки в любой момент.
📦 ЧТО ПОНАДОБИТСЯ:
• Arduino Nano • Модуль GY-521 (гироскоп + акселерометр MPU6050) • OLED-дисплей 0.96" SSD1306 (I2C, 128×64) • Тактовая кнопка 6×6×5 • Зуммер 5V • Провода, паяльник, печатная макетная плата
🔌 СХЕМА ПОДКЛЮЧЕНИЯ:
GY-521 (MPU6050): • VCC → 5V • GND → GND • SCL → A5 • SDA → A4
OLED SSD1306: • VCC → 5V • GND → GND • SCL → A5 • SDA → A4
Кнопка: • Один контакт → D2 • Другой контакт → GND
Зуммер: • (+) → D3 • (–) → GND
Все модули на общей шине I2C.
📚 БИБЛИОТЕКИ:
• Adafruit_GFX • Adafruit_SSD1306 • Wire (встроенная)
Датчик читается напрямую через Wire — никаких дополнительных библиотек для MPU6050 не нужно, работает с любыми модулями GY-521 (включая клоны).
⚙️ КАК ЭТО РАБОТАЕТ:
Ставишь шуруповёрт на ровную поверхность
Нажимаешь кнопку — текущее положение становится нулём
Пузырёк на экране показывает наклон в двух плоскостях
Отклонение меньше 0.5° — надпись «РОВНО» и короткий писк зуммера
Калибровать можно в любой момент — просто жми кнопку ещё раз
Собрал электронный уровень для шуруповёрта своими руками. Показывает наклон по двум осям, при попадании в ноль загорается «РОВНО» и пищит зуммер. Калибровка — одним нажатием кнопки в любой момент.
📦 ЧТО ПОНАДОБИТСЯ:
• Arduino Nano • Модуль GY-521 (гироскоп + акселерометр MPU6050) • OLED-дисплей 0.96" SSD1306 (I2C, 128×64) • Тактовая кнопка 6×6×5 • Зуммер 5V • Провода, паяльник, печатная макетная плата
🔌 СХЕМА ПОДКЛЮЧЕНИЯ:
GY-521 (MPU6050): • VCC → 5V • GND → GND • SCL → A5 • SDA → A4
OLED SSD1306: • VCC → 5V • GND → GND • SCL → A5 • SDA → A4
Кнопка: • Один контакт → D2 • Другой контакт → GND
Зуммер: • (+) → D3 • (–) → GND
Все модули на общей шине I2C.
📚 БИБЛИОТЕКИ:
• Adafruit_GFX • Adafruit_SSD1306 • Wire (встроенная)
Датчик читается напрямую через Wire — никаких дополнительных библиотек для MPU6050 не нужно, работает с любыми модулями GY-521 (включая клоны).
⚙️ КАК ЭТО РАБОТАЕТ:
Ставишь шуруповёрт на ровную поверхность
Нажимаешь кнопку — текущее положение становится нулём
Пузырёк на экране показывает наклон в двух плоскостях
Отклонение меньше 0.5° — надпись «РОВНО» и короткий писк зуммера
Калибровать можно в любой момент — просто жми кнопку ещё раз
#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
#define SCREEN_WIDTH 128
#define SCREEN_HEIGHT 64
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, -1);
#define MPU_ADDR 0x68
float pitch = 0, roll = 0;
float pitchOffset = 0, rollOffset = 0;
bool calibrated = false;
float filterFactor = 0.1;
const int buttonPin = 2;
const int buzzerPin = 3;
void mpuInit() {
Wire.beginTransmission(MPU_ADDR);
Wire.write(0x6B); Wire.write(0); Wire.endTransmission(true);
Wire.beginTransmission(MPU_ADDR);
Wire.write(0x1C); Wire.write(0x10); Wire.endTransmission(true);
delay(100);
}
void readMPU(int16_t &ax, int16_t &ay, int16_t &az) {
Wire.beginTransmission(MPU_ADDR);
Wire.write(0x3B);
Wire.endTransmission(false);
Wire.requestFrom(MPU_ADDR, 6, true);
ax = (Wire.read() << 8) | Wire.read();
ay = (Wire.read() << 8) | Wire.read();
az = (Wire.read() << 8) | Wire.read();
}
void setup() {
Serial.begin(9600);
pinMode(buttonPin, INPUT_PULLUP);
pinMode(buzzerPin, OUTPUT);
digitalWrite(buzzerPin, LOW);
Wire.begin();
delay(100);
if (!display.begin(SSD1306_SWITCHCAPVCC, 0x3C)) {
while (1);
}
mpuInit();
display.clearDisplay();
display.setTextSize(1);
display.setTextColor(SSD1306_WHITE);
display.setCursor(0, 0);
display.println("Place drill level");
display.println("on flat surface");
display.println("and PRESS BUTTON");
display.println("to set ZERO");
display.display();
while (digitalRead(buttonPin) == HIGH) {
delay(50);
}
calibrateZero();
}
void loop() {
int16_t ax, ay, az;
readMPU(ax, ay, az);
float fx = ax / 4096.0;
float fy = ay / 4096.0;
float fz = az / 4096.0;
float rawPitch = atan2(fx, sqrt(fy*fy + fz*fz)) * 180.0 / PI;
float rawRoll = atan2(fy, sqrt(fx*fx + fz*fz)) * 180.0 / PI;
pitch = pitch * (1 - filterFactor) + rawPitch * filterFactor;
roll = roll * (1 - filterFactor) + rawRoll * filterFactor;
float dP = pitch - pitchOffset;
float dR = roll - rollOffset;
if (digitalRead(buttonPin) == LOW) {
calibrateZero();
delay(300);
}
updateDisplay(dP, dR);
if (calibrated && abs(dP) < 0.5 && abs(dR) < 0.5) {
tone(buzzerPin, 2000, 50);
} else {
noTone(buzzerPin);
}
delay(10);
}
void calibrateZero() {
float sP = 0, sR = 0;
int16_t ax, ay, az;
for (int i = 0; i < 50; i++) {
readMPU(ax, ay, az);
float x = ax / 4096.0, y = ay / 4096.0, z = az / 4096.0;
sP += atan2(x, sqrt(y*y + z*z)) * 180.0 / PI;
sR += atan2(y, sqrt(x*x + z*z)) * 180.0 / PI;
delay(5);
}
pitchOffset = sP / 50.0;
rollOffset = sR / 50.0;
calibrated = true;
tone(buzzerPin, 1000, 200);
delay(200);
noTone(buzzerPin);
display.clearDisplay();
display.setTextSize(2);
display.setCursor(10, 20);
display.println("ZERO");
display.display();
delay(500);
}
void updateDisplay(float p, float r) {
display.clearDisplay();
int cx = 64, cy = 32;
float maxAngle = 10.0;
int radius = 28;
int posX = constrain(cx + (r / maxAngle) * radius, 5, SCREEN_WIDTH - 5);
int posY = constrain(cy - (p / maxAngle) * radius, 5, SCREEN_HEIGHT - 5);
display.drawLine(cx, 0, cx, SCREEN_HEIGHT - 1, SSD1306_WHITE);
display.drawLine(0, cy, SCREEN_WIDTH - 1, cy, SSD1306_WHITE);
display.drawCircle(cx, cy, radius, SSD1306_WHITE);
display.fillCircle(posX, posY, 6, SSD1306_WHITE);
display.drawCircle(posX, posY, 6, SSD1306_BLACK);
display.setTextSize(1);
display.setCursor(0, 0);
display.print("P:");
display.print(p, 1);
display.setCursor(0, 10);
display.print("R:");
display.print(r, 1);
if (calibrated && abs(p) < 0.5 && abs(r) < 0.5) {
display.setTextSize(2);
display.setCursor(20, 20);
display.print("ROVNO");
}
display.display();
}
🔥1
🕐 Часы с будильником на Arduino
Простой проект: часы реального времени с будильником, зуммером для тиканья и MP3-модулем для мелодии пробуждения.
📦 Компоненты
— Arduino Uno (или Nano) — 1 шт
— Модуль часов DS1302 — 1 шт
— LCD-экран 1602 с I2C-платой — 1 шт
— DFPlayer Mini — 1 шт
— Динамик 8Ω, 1–3 Вт — 1 шт
— Зуммер (пассивный) — 1 шт
— MicroSD-карта 2–16 ГБ, формат FAT32 — 1 шт
— Резистор 1 кОм — 1 шт
— Кнопки тактовые — 2 шт
— Провода, макетная плата
🔌 Схема подключения
DS1302 (модуль часов):
— VCC → 5V
— GND → GND
— CLK → D5
— DAT → D6
— RST → D7
LCD 1602 (с I2C-платой):
— VCC → 5V
— GND → GND
— SDA → A4
— SCL → A5
DFPlayer Mini:
— VCC → 5V
— GND → GND
— RX → D11 (через резистор 1 кОм!)
— TX → D10
— SPK_1 → динамик «+»
— SPK_2 → динамик «−»
Зуммер:
— «+» (длинная ножка) → D9
— «−» (короткая ножка) → GND
Кнопки:
— Plus → D2 → GND
— Select → D3 → GND
🎵 SD-карта
Отформатируй карту в FAT32. Создай папку mp3 в корне карты. Положи туда один файл 0001.mp3 — это будет мелодия будильника. Любая песня на твой вкус.
Структура:
SD-карта/ → mp3/ → 0001.mp3
Важно: имя файла ровно 4 цифры (0001.mp3), формат mp3, битрейт 128 kbps.
📚 Библиотеки
Установи через Library Manager в Arduino IDE:
— LiquidCrystal I2C (Frank de Brabander)
— Rtc by Makuna (Michael C. Miller)
— DFRobotDFPlayerMini (DFRobot)
🎮 Управление
Долгое нажатие Select — вход или выход из меню.
Короткое нажатие Select — следующий пункт меню: HOUR → MINUTE → ALARM → TICKING → EXIT.
Кнопка Plus — изменить значение выбранного пункта.
⚠️ Важно после первой заливки
Залей скетч как есть — на LCD появится правильное время с компьютера.
Закомментируй эти две строки в setup(): RtcDateTime compiled = RtcDateTime(DATE, TIME); Rtc.SetDateTime(compiled);
Просто поставь // перед каждой строкой. 3. Залей скетч снова. Теперь время не будет сбрасываться при каждом включении. Если хочешь, чтобы время сохранялось при отключении питания — проверь батарейку CR2032 в модуле DS1302. Если она села, время будет сбрасываться.
Простой проект: часы реального времени с будильником, зуммером для тиканья и MP3-модулем для мелодии пробуждения.
📦 Компоненты
— Arduino Uno (или Nano) — 1 шт
— Модуль часов DS1302 — 1 шт
— LCD-экран 1602 с I2C-платой — 1 шт
— DFPlayer Mini — 1 шт
— Динамик 8Ω, 1–3 Вт — 1 шт
— Зуммер (пассивный) — 1 шт
— MicroSD-карта 2–16 ГБ, формат FAT32 — 1 шт
— Резистор 1 кОм — 1 шт
— Кнопки тактовые — 2 шт
— Провода, макетная плата
🔌 Схема подключения
DS1302 (модуль часов):
— VCC → 5V
— GND → GND
— CLK → D5
— DAT → D6
— RST → D7
LCD 1602 (с I2C-платой):
— VCC → 5V
— GND → GND
— SDA → A4
— SCL → A5
DFPlayer Mini:
— VCC → 5V
— GND → GND
— RX → D11 (через резистор 1 кОм!)
— TX → D10
— SPK_1 → динамик «+»
— SPK_2 → динамик «−»
Зуммер:
— «+» (длинная ножка) → D9
— «−» (короткая ножка) → GND
Кнопки:
— Plus → D2 → GND
— Select → D3 → GND
🎵 SD-карта
Отформатируй карту в FAT32. Создай папку mp3 в корне карты. Положи туда один файл 0001.mp3 — это будет мелодия будильника. Любая песня на твой вкус.
Структура:
SD-карта/ → mp3/ → 0001.mp3
Важно: имя файла ровно 4 цифры (0001.mp3), формат mp3, битрейт 128 kbps.
📚 Библиотеки
Установи через Library Manager в Arduino IDE:
— LiquidCrystal I2C (Frank de Brabander)
— Rtc by Makuna (Michael C. Miller)
— DFRobotDFPlayerMini (DFRobot)
🎮 Управление
Долгое нажатие Select — вход или выход из меню.
Короткое нажатие Select — следующий пункт меню: HOUR → MINUTE → ALARM → TICKING → EXIT.
Кнопка Plus — изменить значение выбранного пункта.
⚠️ Важно после первой заливки
Залей скетч как есть — на LCD появится правильное время с компьютера.
Закомментируй эти две строки в setup(): RtcDateTime compiled = RtcDateTime(DATE, TIME); Rtc.SetDateTime(compiled);
Просто поставь // перед каждой строкой. 3. Залей скетч снова. Теперь время не будет сбрасываться при каждом включении. Если хочешь, чтобы время сохранялось при отключении питания — проверь батарейку CR2032 в модуле DS1302. Если она села, время будет сбрасываться.
🎬 Как пользоваться
Часы: на LCD тикает время, внизу статус будильника (AL07:30 ON T) и знак T, если включено тиканье.
Меню: зажми Select на секунду — попадёшь в настройки.
Поставить будильник: коротко жми Select, пока не дойдёшь до HOUR. Жми Plus, чтобы выставить час. Снова Select — MINUTE, Plus — минуты.
Включить/выключить будильник: дойди до ALARM, нажми Plus — переключится ON/OFF.
Включить/выключить тиканье: дойди до TICKING, нажми Plus.
Выход: дойди до EXIT или зажми Select — вернёшься к часам.
Когда сработает будильник — заиграет твоя мелодия из 0001.mp3.
Часы: на LCD тикает время, внизу статус будильника (AL07:30 ON T) и знак T, если включено тиканье.
Меню: зажми Select на секунду — попадёшь в настройки.
Поставить будильник: коротко жми Select, пока не дойдёшь до HOUR. Жми Plus, чтобы выставить час. Снова Select — MINUTE, Plus — минуты.
Включить/выключить будильник: дойди до ALARM, нажми Plus — переключится ON/OFF.
Включить/выключить тиканье: дойди до TICKING, нажми Plus.
Выход: дойди до EXIT или зажми Select — вернёшься к часам.
Когда сработает будильник — заиграет твоя мелодия из 0001.mp3.
#include <Wire.h>
#include <LiquidCrystal_I2C.h>
#include <ThreeWire.h>
#include <RtcDS1302.h>
#include <SoftwareSerial.h>
#include <DFRobotDFPlayerMini.h>
// === LCD ===
LiquidCrystal_I2C lcd(0x27, 16, 2);
// === DS1302 (DAT, CLK, RST) ===
ThreeWire myWire(6, 5, 7);
RtcDS1302<ThreeWire> Rtc(myWire);
// === DFPlayer ===
SoftwareSerial mp3Serial(10, 11);
DFRobotDFPlayerMini mp3;
// === Пины ===
const int btnPlus = 2;
const int btnSelect = 3;
const int buzzerPin = 9;
// === Настройки ===
int alarmHour = 7;
int alarmMin = 30;
bool alarmEnabled = true;
bool tickEnabled = true;
int mode = 0; // 0 = часы, 1 = меню
int field = 0; // 0=HOUR 1=MINUTE 2=ALARM 3=TICKING 4=EXIT
bool ringing = false;
int lastSecond = -1;
bool tickToggle = false;
unsigned long btnSelectStart = 0;
bool btnSelectHeld = false;
unsigned long lastDraw = 0;
// ============================================
void setup() {
pinMode(btnPlus, INPUT_PULLUP);
pinMode(btnSelect, INPUT_PULLUP);
pinMode(buzzerPin, OUTPUT);
lcd.init();
lcd.backlight();
lcd.setCursor(0, 0);
lcd.print("Loading...");
// --- RTC DS1302 ---
Rtc.Begin();
Rtc.SetIsWriteProtected(false);
Rtc.SetIsRunning(true);
// !!! АВТОУСТАНОВКА ВРЕМЕНИ !!!
// Работает только при заливке скетча.
// После того как увидишь правильное время на LCD —
// закомментируй эти 2 строки и залей скетч ещё раз:
RtcDateTime compiled = RtcDateTime(__DATE__, __TIME__);
Rtc.SetDateTime(compiled);
// --------------------------------
if (!Rtc.IsDateTimeValid()) {
lcd.setCursor(0, 1);
lcd.print("RTC error!");
}
// --- DFPlayer ---
mp3Serial.begin(9600);
if (!mp3.begin(mp3Serial)) {
lcd.setCursor(0, 1);
lcd.print("MP3 error!");
} else {
mp3.volume(25);
}
delay(1500);
lcd.clear();
}
// ============================================
void loop() {
handleButtons();
RtcDateTime now = Rtc.GetDateTime();
// --- Тиканье бузера ---
if (tickEnabled && !ringing && now.Second() != lastSecond) {
lastSecond = now.Second();
if (tickToggle) tone(buzzerPin, 2000, 25);
else tone(buzzerPin, 1500, 25);
tickToggle = !tickToggle;
}
// --- Проверка будильника ---
if (mode == 0 && alarmEnabled && !ringing &&
now.Hour() == alarmHour &&
now.Minute() == alarmMin &&
now.Second() < 2) {
ringing = true;
mp3.volume(25);
mp3.playFolder(1, 1); // играет 0001.mp3
}
// --- Обновление экрана ---
if (millis() - lastDraw > 250) {
lastDraw = millis();
if (mode == 0) drawClock(now);
else drawMenu();
}
delay(20);
}
// ============================================
void handleButtons() {
// === Plus: изменить значение ===
if (digitalRead(btnPlus) == LOW) {
delay(30);
if (mode == 1) {
if (field == 0) alarmHour = (alarmHour + 1) % 24;
else if (field == 1) alarmMin = (alarmMin + 1) % 60;
else if (field == 2) alarmEnabled = !alarmEnabled;
else if (field == 3) tickEnabled = !tickEnabled;
}
while (digitalRead(btnPlus) == LOW) delay(10);
}
// === Select: коротко = следующий пункт, долго = вход/выход ===
if (digitalRead(btnSelect) == LOW) {
if (!btnSelectHeld) {
btnSelectHeld = true;
btnSelectStart = millis();
}
} else {
if (btnSelectHeld) {
unsigned long held = millis() - btnSelectStart;
btnSelectHeld = false;
if (held > 800) {
if (mode == 0) { mode = 1; field = 0; lcd.clear(); }
else { mode = 0; lcd.clear(); }
} else {
if (mode == 1) {
field++;
if (field > 4) { mode = 0; lcd.clear(); }
}
}
}
}
}
// ============================================
void drawClock(RtcDateTime now) {
char buf[17];
lcd.setCursor(0, 0);
sprintf(buf, "%02u:%02u:%02u ", now.Hour(), now.Minute(), now.Second());
lcd.print(buf);
lcd.setCursor(0, 1);
sprintf(buf, "AL%02d:%02d %s %c ",
alarmHour, alarmMin,
alarmEnabled ? "ON " : "OFF",
tickEnabled ? 'T' : '-');
lcd.print(buf);
}
// ============================================
void drawMenu() {
char buf[17];
lcd.setCursor(0, 0);
if (field == 0) sprintf(buf, ">HOUR: %02d ", alarmHour);
else if (field == 1) sprintf(buf, ">MINUTE: %02d ", alarmMin);
else if (field == 2) sprintf(buf, ">ALARM: %-3s ", alarmEnabled ? "ON " : "OFF");
else if (field == 3) sprintf(buf, ">TICKING: %-3s ", tickEnabled ? "ON " : "OFF");
else sprintf(buf, ">EXIT ");
lcd.print(buf);
RtcDateTime now = Rtc.GetDateTime();
lcd.setCursor(0, 1);
sprintf(buf, "Now %02u:%02u ", now.Hour(), now.Minute());
lcd.print(buf);
}