К сожалению в програмировании еще новичек. У меня температура высвечивается наоборот. Не могу разобраться, как инвертировать последовательность регистров.
Тут в самом начале был разговор про мерцание цифирь - путем нехитрых опытов выяснил что это резистор звенит. Ради интереса поставил 111 максимальное значение - мерцание исчезло.
Дык, это, мерцание цифирь, или засвет. Я залил оба кода, протестил, в обоих вариантах у меня на индикаторе было мерцание разрядов, вернее не мерцание - цифры менялись оч быстро (я честно говоря с Омом не дружу) я так понял это про это говорилось в начале топика - засвет чегото там был.
111 - это я поставил вместо 8888. число получилось поменьше - цифры перестали мерцать (видать переменный резистор выдаЁт плавающее сопротивление :) )
111 - это я поставил вместо 8888. число получилось поменьше - цифры перестали мерцать (видать переменный резистор выдаЁт плавающее сопротивление :) )
Это Вы про первый скетч?
Там автор для тестов зацепил переменный резистор на аналоговый вход А0 и этим резистором менял на нем входное напряжение от нуля до пяти вольт. При этом, считанные аналоговые значения на входе А0 принимают дисятичное значение от 0 до 1023, с помощью функции map этот диапазон растягивается на диапазонотображения на идикаторе от 0 до 8888, для того, чтоб можно было протестировать работу индикатора.
Вы изменив 8888 на 111 просто сжали диапазон и регулировка стала очень плавной, при этом максимально отображаемое значение на индикаторе у Вас стало 111, то-есть у Вас отображается от 0 до 111 при повороте ручки переменного резистора из одного крайнего положения в другое, а у автора за тот же поворот переменного резистора значение меняется от 0 до 8888, от этого и видимое быстрое изменение символов. Но под мерцанием я так понимаю изначально понималось не это, есть засветка других сегментов, которые не должны гореть в данный момент.
... а у автора за тот же поворот переменного резистора значение меняется от 0 до 8888, от этого и видимое быстрое изменение символов. Но под мерцанием я так понимаю изначально понималось не это, есть засветка других сегментов, которые не должны гореть в данный момент.
Вы все правильно поняли про мою начальную проблему :) .
Gres, Вы очень понятно пишите и объясняете :) Мне бы так! А то порой я весьма косноязычен и мне довольно трудно описать свою проблему или подсказать решение другому человеку.
Я недавно баловался с трехразрядным 7-сегментным индикатором, подключил их, каждый разряд через 176ид3, это дешифратор двоичного кода в 7-сегментный, с защелкой. Микруху можно было и одну использовать, но купил их десяток, по 7 рублей и поставил на каждый разряд, зато больше ничего не нужно и вывод идёт поочерёдно на каждый разряд, но в момент отображения одного разряда, другие два показывают предыдущее значение, а не выключаются. Смотрится очень хорошо при изменении. Правда эта серия питается от 9 вольт. Ну и бонус, данные в порт выводятся в десятичном виде, но тогда остальные ноги порта нужно контролировать, если используются.
// signs to be displayed
volatile unsigned char displayBuffer[] = {~SIGN_0, ~SIGN_F, ~SIGN_F},
Процедура конвертации значения в семисегментное представление:
void fillDisplayBuffer(int value, unsigned char padChar) {
// convert int to string and fill the display buffer
unsigned char i = 3; // digits at display
div_t res; // conversion divider
// padding left
if (value < 100) displayBuffer[0] = padChar;
if (value < 10) displayBuffer[1] = padChar;
// convert integer to string and place it to the buffer
do {
res = div(value, 10);
displayBuffer[--i] = codeTable[res.rem];
value = res.quot;
} while (value != 0 && i != 0);
}
Здравствуйте! Nemo, объясните пожалуйста, как работает обращение к массиву содержащему сегменты? Я всю голову сломал, прямо магия какая-то. Все работает, но я не могу понять как! Конкретно интересует момент из строки 124. Ведь X это посути определенная цифра, как она ссылается на массив, где хранятся сегменты, ведь номер элемента в массиве не соответствует значению этой цифры? Я понимаю, что я ничерта не понимаю в программировании(
SegDisplay=g_digits[x]; // получаем цифру и выводим символ, из массива цифр, соответствующий этой цифре.
Здравствуйте! Nemo, объясните пожалуйста, как работает обращение к массиву содержащему сегменты?
К сожалению, данную тему рассматривал как пробную, и только в качесте первого знакомства с ардуино. Просто не интерестно было мигать светодиодом. Влез чуть по сложнее. Сейчас уже деталей и не вспомню. Многое подсказывали именно на этом форуме другие профи.
Главное - что все работает.
Сейчас полностью ушел от 7-сегментников (в прочем та тренировка была одной из первых, и на том и закончилась). На сегодня - полностью все проекты делаем на LCD-дисплеях. В основном - 4х20. Гораздо проще и намного информативнее.
Доброго времени. Решил я поиграться с таким дисплеем. Вот только у меня дисплей на 14 разрядов, 8 из которыз на 7 сигментов и 6 - квадратики (по 1 сигменту).
Почитал Ваши коды, поигрался. Как итог: если используем код формирования вывода как
if (disp < 0) // Если значение минусовое, то выполняется следующее условие
то все работает нормально на 4 разрядах. А вот на 6, 8, 14,этот код не подходит. Цифры начинают блекнуть. Скорости ардуинки не хватает. Конено, если просто писать число, то все в порядке. Но я просто взял часикии.
Но вот как только перевел вывод в цикл FOR, то тут все становится веселее. Яркость поднялась. А если мне пнадобится кроме часиков и температура, или еще что то. И везде надо прочитать данные, а это время, которое критично для амического режима.
Дисплей,конечно интересный,но мало информативный. Динамическая индикация напрягае ардуинку. Есть ГОТОВЫЕ решения для вывода данных, там за вывод отвечает драйвер и вся работа ложится на него.
/*
********************************************************************
Name : Arduino, 4-разрядный 7-сегментный индикатор, 74HC595 сдвиговый регистр, DS1307 RTC
Author : CheBuraw
Date : 12 Feb, 2015
Optimiser: Datak
Version : 1.1
********************************************************************
4-разрядный 7-сегментный индикатор. общий анод
1 A F 2 3 B
_______________|__|__|__|__|__|_____________
| | | | | |
| A | A | | A | A |
| F B | F B | dp | F B | F B |
| G | G | | G | G |
| E C | E C | dp | E C | E C |
| D | D | | D | D |
|_________|_________|____|_________|_________|
| | | | | |
E D dp C G 4
74HC595 Map:
_______
Q1 |1 * 16| Vcc PINS 1-7, 15 Q0 - Q7 Output Pins
Q2 |2 15| Q0 PIN 8 GND Ground, Vss
Q3 |3 14| DS PIN 9 Q7" Serial Out
Q4 |4 13| OE PIN 10 MR Master Reclear, active low
Q5 |5 12| ST_CP PIN 11 SH_CP Shift register clock pin
Q6 |6 11| SH_CP PIN 12 ST_CP Storage register clock pin (latch pin)
Q7 |7 10| MR PIN 13 OE Output enable, active low
GND |8_____9| Q7" PIN 14 DS Serial data input
PIN 16 Vcc Positive supply voltage
_______
LED B -|1 * 16|-5V
LED C -|2 15|-LED A
LED D -|3 14|-PIN 11
LED E -|4 13|-GND
LED F -|5 12|-PIN 8
LED G -|6 11|-PIN 12 ; 1uF TO GND
LED dp-|7 10|-5V
GND-|8_____9|-NILL
*/
#include <Wire.h>
#include "RTClib.h"
RTC_DS1307 RTC;
int latchPin = 7; //Пин "защелки" первого регистра подключен к ST_CP (RCLK)входу первого регистра отвечающего за сегменты
int clockPin = 6; //Пин подключен к SH_CP входу 74HC595 (SCLK)
int dataPin = 5; //Пин подключен к DS входу 74HC595 (DIO)
int TimeLight = 5; //время для разогрева сегментов
byte SegDisplay; // переменная для вывода символов на индикаторе
byte RazrDisplay; // переменная для включения разрядов
// Настройка комбинации для отображения каждого номера на дисплее.
byte g_digits[11]={
B01000000, B01111001, // 0 1
B00100100, B00110000, // 2 3
B00011001, B00010010, // 4 5
B00000010, B01111000, // 6 7
B00000000, B00010000, // 8 9
B11111111, }; // все сегменты выключены
byte g_registerArray[4]={8,4,2,1}; //массив цифр, указывающий разряды
void setup() {
Wire.begin();
RTC.begin();
// обозначаем все пины как выходы
pinMode(latchPin, OUTPUT);
pinMode(clockPin, OUTPUT);
pinMode(dataPin, OUTPUT);
}
void loop() {
int hour,minute,disp = 0;
DateTime now = RTC.now(); //Создаём переменную для вывода времени
hour = now.hour(); // Считываем значение часов
minute = now.minute(); // Считываем значение минут
disp = (hour * 100) + minute; //"Собираем" значения часов и минут в одну цифру
// Разбиваем цифру по разрядам индикатора
for( int i = 0; i < 4; i++ )
{
if( i == 0 || disp != 0 )
Indicate( i, disp % 10 );
else
Indicate( i, 10 );
disp /= 10;
}
}
void Indicate(int r,int x)
{
SegDisplay=g_digits[x]; // получаем цифру и выводим символ, из массива цифр, соответствующий этой цифре.
RazrDisplay=g_registerArray[r]; // получаем цифру и выводим номер регистра, из массива цифр, соответствующий этой цифре.
digitalWrite(latchPin, LOW); // устанавливаем синхронизацию "защелки" на LOW
shiftOut(dataPin, clockPin, MSBFIRST, RazrDisplay); // Записываем информацию для первого регистра (Номер разряда)
shiftOut(dataPin, clockPin, MSBFIRST, SegDisplay); // Записываем информацию для второго регистра (Номер символа)
digitalWrite(latchPin, HIGH); //"защелкиваем" регистр, тем самым устанавливая значения на выходах
delay(TimeLight); // пауза, чтобы сегменты "разгорелись"
}
Разбиваешь часики на константы (как часы, минуты, секунды) или просто из строки как из массива тянешь знак, ну и это все выкидываешь в функцию voidIndicate(intr,intx). Правда дисплей у меня другой и разделителя нет в виде точек " : " . Пришлось использовать dp второго сигмента как B11000000 == 0. Тоесть присваивание бита к int. B01000000 можите еще один массив с точками прописать. Как Вам угодно.
Разбиваешь часики на константы (как часы, минуты, секунды) или просто из строки как из массива тянешь знак, ну и это все выкидываешь в функцию voidIndicate(intr,intx). Правда дисплей у меня другой и разделителя нет в виде точек " : " . Пришлось использовать dp второго сигмента как B11000000 == 0. Тоесть присваивание бита к int. B01000000 можите еще один массив с точками прописать. Как Вам угодно.
как начальные значения времени вводятся. я смотрю все только на уровне бумаги делают, а в работе не идет. Время с потолка кажеться
Всю тему не осилил. К вопросу в первом посте две поправки: 1. shifhOut - выкинуть, он меделенный, 2. засветы развести за счет небольших задержек между гашением и включением катодов. Ниже код для часового секундомера с обратным отсчетом времени (с пищалкой) на примере Ардуино Мега и Attiny, в принципе подойдет для любого, главное чтобы все ножки SPI на одном порту были. Частота обновления кадров порядка тысячи-двух кадров в секунду.
Вариант выделенного "драйвера индикатора" на Attiny. Число передается по UART от внешнего источника, Тинька его принимает и крутит на индикаторе. Освобождает главный МК от необходимости делать это самостоятельно.
//
// индикатор на ATTINY85/13
// компилить на 8МГц
// фьюзы DF, E2
#include <SoftwareSerial.h>
#define rx 3
#define tx 4
SoftwareSerial mySerial(rx, tx);
#define DATA_PIN 2 // индикатор пины
#define LATCH_PIN 1
#define CLOCK_PIN 0
int Val = 1234;
int i = 0;
char buf[8];
byte segment [12] = {
0b11101110, 0b00100101, 0b01111011, 0b01110111, 0b10110101,
0b11010111, 0b11011111, 0b01100101, 0b11111111, 0b11110111,
0b00000000, 0b01010011,
};
byte razr [4] = {0b11100000, 0b11010000, 0b10110000, 0b01110000};
void setup() {
pinMode(DATA_PIN, OUTPUT);
pinMode(CLOCK_PIN, OUTPUT);
pinMode(LATCH_PIN, OUTPUT);
pinMode(rx, INPUT);
pinMode(tx, OUTPUT);
mySerial.begin(9600);
// Serial.begin(9600);
}
void loop() {
setDisp(Val); // выводим число на индикатор
//Serial.println(Val,DEC);
if (mySerial.available() > 0) {
buf[i] = mySerial.read();
//Val=int(buf[3]) - 0x30;
if (int(buf[i]) == 10) { // || int(buf[i]) == 10) {
Val = (buf[1] - 0x30) * 1000 + (buf[2] - 0x30) * 100 + (buf[3] - 0x30) * 10 + (buf[4] - 0x30);
i = 0;
}
i++;
}
}
void setDisp (int Val) { // вывод на индикатор
byte digit;
for (byte i = 0; i < 4; i++) {
switch (i) {
case 0:
digit = Val / 1000;
break;
case 1:
digit = Val / 100 % 10;
break;
case 2:
digit = Val / 10 % 10;
break;
case 3:
digit = Val % 10;
break;
}
byte segRaz = razr[i];
byte segDig = segment[digit];
PDdigWL(LATCH_PIN);
writeByteP(segRaz);
writeByteP(segDig);
PDdigWH(LATCH_PIN);
if (i < 3) delayMicroseconds(150); // выравнивание яркости (200мкс)
}
}
inline void writeByteP(byte byteW) { // аналог shiftOut, работает намного быстрее
for (byte i = 0; i <= 7; i++)
{
if (bitRead(byteW, i)) {
PDdigWH(DATA_PIN);
} else {
PDdigWL(DATA_PIN);
}
PDdigWH(CLOCK_PIN);
PDdigWL(CLOCK_PIN);
}
}
inline void PDdigWH(byte NB) {
PORTB |= 1 << NB;
}
inline void PDdigWL(byte NB) {
PORTB &= ~(1 << NB);
}
А вот вариант для секундомера на Attiny, катоды и аноды на ножках МК. Засвет идеально ровный за счет доводки таймингов по осциллографу.
// индикатор на ATTINY2313
// компилить на 8МГц
// фьюзы HDF, LE4 - внутренний резонатор 8МГц (требуется подстройка OSCCAL)
// фьюзы HDF, LDE - внешний кварц 8МГц (рекомендуется)
unsigned int Val;
// i = 0;
unsigned int digit;
byte MIN = 60;
byte SEC = 00;
long timerSEC;
long timerBEEP;
long timerPRESS;
bool BEEP;
bool DOT;
bool oldPress = 0;
#define trimming 20 // время на антидребезг
#define oneSec 1000 // 1 секунда
#define longPress 2000 // длинное нажатие (мин)
byte segment [10] = {
0b00111111, 0b00000110, 0b01011011, 0b01001111, 0b01100110,
0b01101101, 0b01111101, 0b00000111, 0b01111111, 0b01101111,
};
void(* resetFunc) (void) = 0;
void setup() {
// OSCCAL = 80; // подкрутка генератора (для каждого МК свой) по умолчанию 96 на 8МГц (чем меньше тем делает медленней)
DDRB = 0b11111111; //76543210
DDRD = 0b00111101; //NNGGGGKP
// timerDOT
MIN = 60; //60;
SEC = 00; //00
Val = MIN * 100 + SEC;
PORTB |= (1 << 7);
DOT = 1;
while (PIND & 2) setDisp(Val);
delay(trimming);
while (~PIND & 2) setDisp(Val);
delay(trimming);
beep(500);
timerSEC = millis() + oneSec;
}
void loop() {
setDisp(Val); // выводим число на индикатор
beepStop();
if (timerSEC <= millis()) { // минус секунда
(DOT) ? (PORTB &= ~(1 << 7)) : (PORTB |= (1 << 7)); // точка
DOT = !DOT;
if (!SEC) {
if (!MIN) Stop(); // закончили своим ходом
MIN--;
SEC = 59;
} else {
SEC--;
}
timerSEC = millis() + oneSec;
Val = MIN * 100 + SEC;
if (Val == 3000) beep(500);
if (Val == 1000) beep(500);
if (Val == 500) beep(1000);
}
if (!(PIND & 2)) { // остановка таймера кнопкой
delay(trimming);
timerPRESS = millis();
while (~PIND & 2) {
setDisp(Val);
beepStop();
}
delay(trimming);
if ((millis() - timerPRESS) > longPress) {
Reset();
} else {
Pause();
}
}
if (PIND & 64) { // остановка таймера окончанием задания
Stop();
}
}
inline void beep (int ms) {
timerBEEP = millis() + ms;
PORTD |= 1;
BEEP = 1;
}
inline void beepStop () {
if (BEEP) {
if (timerBEEP < millis()) {
PORTD &= ~1;
BEEP = 0;
}
}
}
void Pause() {
beep(200);
while (PIND & 2) {
setDisp(Val);
beepStop();
if (timerSEC <= millis()) { // минус секунда
(DOT) ? (PORTB &= ~(1 << 7)) : (PORTB |= (1 << 7)); // точка
DOT = !DOT;
timerSEC = millis() + 100;
}
}
delay(trimming);
timerPRESS = millis();
while (~PIND & 2) setDisp(Val);
delay(trimming);
if ((millis() - timerPRESS) > longPress) Reset();
beep(200);
}
void Reset () {
resetFunc();
}
void Stop() {
// Val = 0;
timerSEC = millis() + 2000;
beep(1000);
while (timerSEC > millis()) {
setDisp(Val);
beepStop();
}
while (PIND & 2) setDisp(Val);
delay(trimming);
while (~PIND & 2) setDisp(Val);
delay(trimming);
resetFunc();
}
inline void setDisp (int Val) { // вывод на индикатор
for (byte ii = 0; ii < 4; ii++) {
switch (ii) {
case 0:
digit = Val / 1000;
break;
case 1:
digit = Val / 100 % 10;
break;
case 2:
digit = Val / 10 % 10;
break;
case 3:
digit = Val % 10;
break;
}
// PORTD |= 0b00111100;
PORTD |= 0b00111100;
PORTB &= 0b10000000;
delayMicroseconds(2);
PORTB |= segment[digit];
PORTD &= ~(1 << (ii + 2));
if (ii != 3) delayMicroseconds(150); // выравниваем яркость разрядов
}
}
Все скетчи рабочие, выдраны из готовых устройств.
Есть еще интересый вариант на базе специальной микросхемы TM1380, но это уже другая история.
Может кто из местных гуру найдет ошибку в выводе информации на дисплей. 4-х битный 7-сегментный модуль на сдвиговых регистрах 595-х. В сериале все нормально работает показывает, а на дисплей переменные не выводит. Константы выводит нормально.
//Термогигрометр на SHT и семисегмнтном индикаторе
int latchPin = 7; // Пин "защелки" первого регистра подключен к RCLK (SS, ST_CP) входу
int clockPin = 6; // Пин "тактовый" подключен к SCLK (CLK, SH_CP) входу 74HC595
int dataPin = 5; // Пин "данных" подключен к QH (SDI, DS) входу 74HC595
int TimeLight = 5; // time для разогрева сегментов
byte SegDisplay; // Переменная для вывода символов на индикаторе
byte RazrDisplay; // Переменная для включения разрядов
// Настройка комбинации для отображения каждого номера на индикаторе
// Массив цифр, генерирующий на сегментах цифры в двоичной системе исчисления
byte g_digits[25]={
B11000000, B11111001, B10100100, B10110000, B10011001, // 0 1 2 3 4
B10010010, B10000010, B11111000, B10000000, B10010000, // 5 6 7 8 9
B01000000, B01111001, B00100100, B00110000, B00011001, // 0. 1. 2. 3. 4.
B00010010, B00000010, B01111000, B00000000, B00010000, // 5. 6. 7. 8. 9.
B01111111, B10111111, B10011100, B11000110, // ., -, °, С
B11111111, }; // all segm.
byte g_registerArray[4]={1,2,4,8}; //массив цифр, указывающий разряды
#include <SHT1x.h>
// Data and Сlock датчика SHT1x
#define dataPin 10
#define clockPin 11
SHT1x sht1x(dataPin, clockPin);
int temp_c=0; // Переменная для целых чисел температуры
int humidity=0; // Переменная для целых чисел влажности
void setup()
{
Serial.begin(9600);
// pin
pinMode(latchPin, OUTPUT);
pinMode(clockPin, OUTPUT);
pinMode(dataPin, OUTPUT);
}
void loop()
{
temp_c = sht1x.readTemperatureC();
Serial.print(temp_c);
Indicate(0, 22); // °
Indicate(1, (temp_c % 10)); // пишем во второй разряд - последнюю целую цифру
Indicate(2, (temp_c % 100) / 10); // пишем в третий разряд - цифру оставшуюся от деления на 100
Indicate(3, (temp_c / 100)); // пишем в четвертый разряд - цифру делёную на 100
delay(2000);
humidity = sht1x.readHumidity();
Serial.print(humidity);
Indicate(0, 21); // -
Indicate(1,(humidity % 10)+10); // пишем во второй разряд - цифру оставшуюся от деления на 10 с точкой
Indicate(2, humidity / 10); // пишем в третий разряд - цифру оставшуюся от деления на 10
Indicate(3, 21); // -
delay(2000);
}
void Indicate(int r,int x) // Функция собственно, отображения цыфр на индикаторе.
{
SegDisplay=g_digits[x]; // получаем цифру и выводим символ, из массива цифр, соответствующий этой цифре.
RazrDisplay=g_registerArray[r]; // получаем цифру и выводим номер регистра, из массива цифр, соответствующий этой цифре.
digitalWrite(latchPin, LOW); // устанавливаем синхронизацию "защелки" на LOW
shiftOut(dataPin, clockPin, MSBFIRST, SegDisplay); // Записываем информацию для первого регистра (Номер символа)
shiftOut(dataPin, clockPin, MSBFIRST, RazrDisplay); // Записываем информацию для второго регистра (Номер разряда)
// shiftOut(dataPin, clockPin, MSBFIRST, SegDisplay); // Записываем информацию для первого регистра (Номер символа)
digitalWrite(latchPin, HIGH); //"защелкиваем" регистр, тем самым устанавливая значения на выходах
delay(TimeLight); // пауза, чтобы сегменты "разгорелись"
}
Что я Вам могу посоветовать. Вот накидал код, проверил. ПРАВДА я не стал циклом перебор выводимого "числа" делать, а просто определил место вывода. Все работает. НО! у меня дисплей немного не как у Вас. Смысл главное.
#include <Wire.h>
#include "RTClib.h"
RTC_DS1307 RTC;
int latchPin = 2; //Пин "защелки" первого регистра подключен к ST_CP входу первого регистра отвечающего за сегменты
int clockPin = 3; //Пин подключен к SH_CP входу 74HC595
int dataPin = 4; //Пин подключен к DS входу 74HC595
int TimeLight = 2; //время для разогрева сегментов
byte SegDisplay; // переменная для вывода символов на индикаторе
byte RazrDisplay; // переменная для включения разрядов
// Настройка комбинации для отображения каждого номера на дисплее.
byte g_digits[17]={
B00111111, B00000110, // 0 1
B01011011, B01001111, // 2 3
B01100110, B01101101, // 4 5
B01111101, B00000111, // 6 7
B01111111, B01101111, // 8 9
B00000000,
B00000001, // A 11
B00000010, // B 12
B00000100, // C 13
B00001000, // C 14
B00010000, // C 15
B00100000, // C 16
}; //
byte g_digits1[11]={
B10111111, B10000110, // 0 1
B11011011, B11001111, // 2 3
B11100110, B11101101, // 4 5
B11111101, B10000111, // 6 7
B11111111, B11101111, // 8 9
B00000000,
};
byte g_registerArray[8]={~32,~16,~8,~4,~2,~1,~128,~64}; //массив цифр, указывающий разряды
byte g_button[8];
// задаем константы
const int buttonPin1 = 12; // номер входа, подключенный к кнопке
const int buttonPin2 = 11;
// переменные
int buttonState1 = 0; // переменная для хранения состояния кнопки
int buttonState2 = 0;
void setup() {
Wire.begin();
RTC.begin();
// обозначаем все пины как выходы
pinMode(latchPin, OUTPUT);
pinMode(clockPin, OUTPUT);
pinMode(dataPin, OUTPUT);
// инициализируем пин, подключенный к кнопке, как вход
pinMode(buttonPin1, INPUT); pinMode(buttonPin2, INPUT);
}
void loop() {
DateTime now = RTC.now();
int hour,minute,disp,sec = 0;
//Serial.print(now.hour(), DEC);
hour = now.hour(); // Считываем значение часов
minute = now.minute(); // Считываем значение минут
sec=now.second();
//disp = (hour * 100) + minute; //"Собираем" значения часов и минут в одну цифру
if (minute < 10) // если наша цифра меньше 10, то
{
Indicate(3, 0); // пишем в третий разряд пусто
Indicate(2, minute); // пишем в четвертый разряд нашу цифру
}
if (minute > 9) // если наша цифра меньше 10, то
{
Indicate(3, minute /10); // пишем в третий разряд пусто
Indicate(2, minute % 10); // пишем в четвертый разряд нашу цифру
}
if (hour < 10) // если наша цифра меньше 10, то
{
Indicate(5, 0); // пишем в третий разряд пусто
Indicate(4, hour); // пишем в четвертый разряд нашу цифру
}
if (hour > 9) // если наша цифра меньше 10, то
{
Indicate(5, hour /10); // пишем в третий разряд пусто
Indicate(4, hour% 10); // пишем в четвертый разряд нашу цифру
}
if (sec < 10) // если наша цифра меньше 10, то
{
Indicate(1, 0); // пишем в третий разряд пусто
Indicate(0, sec); // пишем в четвертый разряд нашу цифру
}
if (sec > 9) // если наша цифра меньше 10, то
{
Indicate(1, sec /10); // пишем в третий разряд пусто
Indicate(0, sec% 10); // пишем в четвертый разряд нашу цифру
}
///////////////////////////////////////////////////
// считываем значения с входа кнопки
buttonState1 = digitalRead(buttonPin1);
buttonState2 = digitalRead(buttonPin2);
// проверяем нажата ли кнопка
// если нажата, то buttonState1 будет HIGH:
if (buttonState1 == HIGH){
// включаем светодиод
g_button[0]=1;
}
if (buttonState2 == HIGH) {
g_button[0]=0;
}
if(g_button[0]==1){
Indicate(7, 11);
}else {
Indicate(7, 10);
}
if(g_button[1]==1){
Indicate(6, 14);
}else {
Indicate(6, 10);
}
// Зажигаем точки слева
//Indicate(7, 11);
//Indicate(7, 12);
// Indicate(7, 13);
// Зажигаем точки справа
// Indicate(6, 14);
// Indicate(6, 15);
// Indicate(6, 16);
}
void Indicate(int r,int x)
{
if(r==4){
SegDisplay=g_digits1[x]; // получаем цифру и выводим символ, из массива цифр, соответствующий этой цифр}е.
}
else{
SegDisplay=g_digits[x]; // получаем цифру и выводим символ, из массива цифр, соответствующий этой цифре.
}
RazrDisplay=g_registerArray[r]; // получаем цифру и выводим номер регистра, из массива цифр, соответствующий этой цифре.
digitalWrite(latchPin, LOW); // устанавливаем синхронизацию "защелки" на LOW
shiftOut(dataPin, clockPin, MSBFIRST, RazrDisplay); // Записываем информацию для второго регистра (Номер разряда)
shiftOut(dataPin, clockPin, MSBFIRST, SegDisplay); // Записываем информацию для первого регистра (Номер символа)
digitalWrite(latchPin, HIGH); //"защелкиваем" регистр, тем самым устанавливая значения на выходах
// delay(5);
}
спасибо Вам за идею и тему, удалось подключить выпяный из старого сломанного DVD экранчик, работает зараза! Пришлось потанцевать, но все получилось, очень помогли Ваши коментарии в скетче.
Всем, кто приложил руки, к окончательному варианту, так же огромное спасибо!
как подключить - последовательно, это же динамическая индикация, выше все описано. Схема стандартная. Разницы нет сколько сигментов используете. Обычная математика. Увеличивается число управляемых элементов.
Завалялся у меня такой индикатор, решил подклчить в проект. Из этого примера решил сделать библиотеку. Раньше я ничем подобным не занимался, поэтому возникили сложности.
Назовем библиотеку Display7
Код для Display7.h
/*
Display7.h - Library for use 4LED display with 2 TM74HC595.
Created by B R, October 8, 2016.
*/
#ifndef Display7_h
#define Display7_h
class Display7
{
public:
Display7 (int clockPin, int latchPin, int dataPin);
void ledDigitDisplay(float temperature);
void Indicate();
private:
int _clockPin;
int _latchPin;
int _dataPin;
};
#endif
Код Display7.cpp
/*
Display7.cpp - Library
*/
#include "Display7.h"
#include <Arduino.h>
Display7::Display7(int clockPin, int latchPin, int dataPin)
{
pinMode(latchPin, OUTPUT);
pinMode(clockPin, OUTPUT);
pinMode(dataPin, OUTPUT);
_clockPin = clockPin;
_latchPin = latchPin;
_dataPin = dataPin;
byte digits[4] = {255,255,255,255};
}
const byte table[11] = {
B11000000, B11111001, B10100100, B10110000, B10011001, // 0 1 2 3 4
B10010010, B10000010, B11111000, B10000000, B10010000, // 5 6 7 8 9
B10111111}; // минус
void ledDigitDisplay(float temperature)
{
int disp = temperature * 100; // Избавляемся от десятых и сотых (оставляем челую часть числа)
if(disp < -5500 || disp > 12500)
{
// Обработаем выход за пределы min и max температур
for (int i = 0; i < 4; i++)
digits[4] = table[10]; // Ставим во всех разрядах прочерки
return;
}
bool point = 0;
if(disp < -999 || disp > 9999) disp /= 10;
else point = 1;
if(disp < 0)
{
digits[3] = table[10];
disp *= -1;
}
else digits[3] = table[disp/1000];
for(byte i = 0; i < 3; i++)
{
digits[i] = table[disp%10];
disp /= 10;
}
if(point) digits[2] &= B01111111; // точка
else digits[1] &= B01111111; // точка
}
void Indicate() // Функция отображения цифр на индикаторе.
{
static uint32_t premillis = 0;
if(millis()-premillis < 2) return;
premillis = millis();
static byte digit = 0;
digitalWrite(latchPin, LOW);
shiftOut(dataPin, clockPin, MSBFIRST, digits[digit]); // символ
shiftOut(dataPin, clockPin, MSBFIRST, 1<<digit); // разряд
digitalWrite(latchPin, HIGH); //"защелкиваем"
digit++;
if(digit == 4) digit = 0;
}
Ну и сам пример для проверки.
#include <Display7.h>
int latchPin = 6;
int clockPin = 9;
int dataPin = 7;
void setup() {
// put your setup code here, to run once:
pinMode(latchPin, OUTPUT);
pinMode(clockPin, OUTPUT);
pinMode(dataPin, OUTPUT);
}
void loop() {
// put your main code here, to run repeatedly:
ledDigitDisplay(12.34);
Indicate();
}
Выдает ошибку что функции в loop не заданы. Где прокол? Камнями не кидайте.
#include <Display7.h>
int latchPin = 6;
int clockPin = 9;
int dataPin = 7;
void setup() {
// put your setup code here, to run once:
pinMode(latchPin, OUTPUT);
pinMode(clockPin, OUTPUT);
pinMode(dataPin, OUTPUT);
}
void loop() {
// put your main code here, to run repeatedly:
ledDigitDisplay(12.34);
Indicate();
}
Выдает ошибку что функции в loop не заданы. Где прокол? Камнями не кидайте.
Вообще, на самом деле меня в первую очередь интересует, как в этом коде сделать так, чтобы полученное значение дисплей показывал скажем 5 секунд.
Т.е, пусть будет температура. Получил я значение 23.50 и мне нужно тображать его 5 секунд. Внезависимости от того, что температура за бортом изменилась.
Вообще, на самом деле меня в первую очередь интересует, как в этом коде сделать так, чтобы полученное значение дисплей показывал скажем 5 секунд.
Т.е, пусть будет температура. Получил я значение 23.50 и мне нужно тображать его 5 секунд. Внезависимости от того, что температура за бортом изменилась.
Я думаю стоит начать с изучения языка программирования и принципов программирования, потом читать ошибки и варнинги компилчтора, а потом вам нужен будет таймер.
Я думаю стоит начать с изучения языка программирования и принципов программирования, потом читать ошибки и варнинги компилчтора, а потом вам нужен будет таймер.
Я думаю, что если нечего сказть, то следует помолчать.
Нет желание отвечать на четкий вопрос, нечего и клавиши напрягать.
Я думаю стоит начать с изучения языка программирования и принципов программирования, потом читать ошибки и варнинги компилчтора, а потом вам нужен будет таймер.
Я думаю, что если нечего сказть, то следует помолчать.
Нет желание отвечать на четкий вопрос, нечего и клавиши напрягать.
Вопрос? Не смешите. У вас целая задача и вы хотите ее решения
. И более четкого не звучало. Вы не знаете как библу подключить и как пользоваться ее функциями. И начали с этого, а потом хотелки свистелки полетели. Изучите теорию.
Как подключить библиотеку не знаю? С чего вы это взяли? Как сделать библиотеку - не знаю. Это да. Потому что ни разу не делал. Но этот вопрос в целом не актуальный, а актуальный по ссылке.
Еще раз, есть что сказать по сути моего вопроса?
PS. Эту библиотеку делал я на основе кода, а не подключал. В отличии от вас, я ее не спрашивал у автора кода, а попытался сделать сам. Делал я ее потому что надо решить вопрос продолжительного свечения результата. Но пока делал, понял что то что хочу не получится.
А не могли бы вы подсказать, как в вашем коде сделать настройку часов с кнопок?
Повторил ваш проект, все работает
Спасибо, что все работает. Тут такое дело. Я перевел "ЭТО безобразие" на ESP8266. Через WIFI, по MQTT проще менять и подстраивать данные, часы то же. НО! Часы, как модуль, можно выкинуть, хотя идут почти точно. Данные времени можено брать из GOOGle. Давно хотел объединить все проекты в доме.
По кнопачкам и настройке часов. Поставте модуль WiFi или bluetooth, и по Tx/Rx гоняйте данные с телефона. Но лучше esp8266.
Всем привет пытаюсь подключить 6 сегментный индикатор на двух сдвиговых регистрах . Но работает только три сегмента и первый сегмент дублирует третий . Тоесть например цыфра 36 выводится как 636. В чем причина подскажите ??
Всем привет пытаюсь подключить 6 сегментный индикатор на двух сдвиговых регистрах . Но работает только три сегмента и первый сегмент дублирует третий . Тоесть например цыфра 36 выводится как 636. В чем причина подскажите ??
Так же возможен и 4 вариант - просто оптимизировать код:
Только не знаю на какие цифры поменять для общего катода byte digits[4] = {255,255,255,255}; ?
К сожалению в програмировании еще новичек. У меня температура высвечивается наоборот. Не могу разобраться, как инвертировать последовательность регистров.
Вообщем можно сказать "методом научного тыка" инвертировал показания регистров
но вот с точкой не получается решить
Спасибо! Пробывал digit>>8. Не получалось.
Пока вы здесь, подскажите пожалуйста нужно ли вообще тут что то менять "byte digits[4] = {255,255,255,255}; " для индикатора с общим катодом?
Самый простой, но не самый правильный способ, это просто инвертировать значения перед выводом в регистры:
Тут в самом начале был разговор про мерцание цифирь - путем нехитрых опытов выяснил что это резистор звенит. Ради интереса поставил 111 максимальное значение - мерцание исчезло.
defezit, честно говоря непонятно о каком резисторе идёт речь. И правильно ли я понял что 111 это значение того самого резистора в Ом`ах?
Дык, это, мерцание цифирь, или засвет. Я залил оба кода, протестил, в обоих вариантах у меня на индикаторе было мерцание разрядов, вернее не мерцание - цифры менялись оч быстро (я честно говоря с Омом не дружу) я так понял это про это говорилось в начале топика - засвет чегото там был.
111 - это я поставил вместо 8888. число получилось поменьше - цифры перестали мерцать (видать переменный резистор выдаЁт плавающее сопротивление :) )
Это Вы про первый скетч?
Там автор для тестов зацепил переменный резистор на аналоговый вход А0 и этим резистором менял на нем входное напряжение от нуля до пяти вольт. При этом, считанные аналоговые значения на входе А0 принимают дисятичное значение от 0 до 1023, с помощью функции map этот диапазон растягивается на диапазонотображения на идикаторе от 0 до 8888, для того, чтоб можно было протестировать работу индикатора.
Вы изменив 8888 на 111 просто сжали диапазон и регулировка стала очень плавной, при этом максимально отображаемое значение на индикаторе у Вас стало 111, то-есть у Вас отображается от 0 до 111 при повороте ручки переменного резистора из одного крайнего положения в другое, а у автора за тот же поворот переменного резистора значение меняется от 0 до 8888, от этого и видимое быстрое изменение символов. Но под мерцанием я так понимаю изначально понималось не это, есть засветка других сегментов, которые не должны гореть в данный момент.
... а у автора за тот же поворот переменного резистора значение меняется от 0 до 8888, от этого и видимое быстрое изменение символов. Но под мерцанием я так понимаю изначально понималось не это, есть засветка других сегментов, которые не должны гореть в данный момент.
Но ту, начальную проблему мы с Datak уже решили:
http://arduino.ru/forum/proekty/vyvod-informatsii-na-4-razryadnyi-7segme...
Gres, Вы очень понятно пишите и объясняете :) Мне бы так! А то порой я весьма косноязычен и мне довольно трудно описать свою проблему или подсказать решение другому человеку.
Я недавно баловался с трехразрядным 7-сегментным индикатором, подключил их, каждый разряд через 176ид3, это дешифратор двоичного кода в 7-сегментный, с защелкой. Микруху можно было и одну использовать, но купил их десяток, по 7 рублей и поставил на каждый разряд, зато больше ничего не нужно и вывод идёт поочерёдно на каждый разряд, но в момент отображения одного разряда, другие два показывают предыдущее значение, а не выключаются. Смотрится очень хорошо при изменении. Правда эта серия питается от 9 вольт. Ну и бонус, данные в порт выводятся в десятичном виде, но тогда остальные ноги порта нужно контролировать, если используются.
Как-то у вас знакогенератор (синтез цифр из сегментов) сильно переусложнен. Я обычно делаю вот так:
Тут сразу видно, какой сегмент подключен к какому пину порта.
Далее столь же наглядно "синтезируем" цифры из сегментов:
Пишем таблицу соотвествия:
Буфер дисплея:
Процедура конвертации значения в семисегментное представление:
Здравствуйте! Nemo, объясните пожалуйста, как работает обращение к массиву содержащему сегменты? Я всю голову сломал, прямо магия какая-то. Все работает, но я не могу понять как! Конкретно интересует момент из строки 124. Ведь X это посути определенная цифра, как она ссылается на массив, где хранятся сегменты, ведь номер элемента в массиве не соответствует значению этой цифры? Я понимаю, что я ничерта не понимаю в программировании(
SegDisplay=g_digits[x];
// получаем цифру и выводим символ, из массива цифр, соответствующий этой цифре.
Много уважаемый ТС, как на счет библиотеки? Кто-то обещал )
Здравствуйте! Nemo, объясните пожалуйста, как работает обращение к массиву содержащему сегменты?
К сожалению, данную тему рассматривал как пробную, и только в качесте первого знакомства с ардуино. Просто не интерестно было мигать светодиодом. Влез чуть по сложнее. Сейчас уже деталей и не вспомню. Многое подсказывали именно на этом форуме другие профи.
Главное - что все работает.
Сейчас полностью ушел от 7-сегментников (в прочем та тренировка была одной из первых, и на том и закончилась). На сегодня - полностью все проекты делаем на LCD-дисплеях. В основном - 4х20. Гораздо проще и намного информативнее.
Как не соответствует? Все соответствовало. У меня все пошло с первого раза, единственное инвертировал цвета и все работает.
Доброго времени. Решил я поиграться с таким дисплеем. Вот только у меня дисплей на 14 разрядов, 8 из которыз на 7 сигментов и 6 - квадратики (по 1 сигменту).
Почитал Ваши коды, поигрался. Как итог: если используем код формирования вывода как
то все работает нормально на 4 разрядах. А вот на 6, 8, 14,этот код не подходит. Цифры начинают блекнуть. Скорости ардуинки не хватает. Конено, если просто писать число, то все в порядке. Но я просто взял часикии.
Но вот как только перевел вывод в цикл FOR, то тут все становится веселее. Яркость поднялась. А если мне пнадобится кроме часиков и температура, или еще что то. И везде надо прочитать данные, а это время, которое критично для амического режима.
Дисплей,конечно интересный,но мало информативный. Динамическая индикация напрягае ардуинку. Есть ГОТОВЫЕ решения для вывода данных, там за вывод отвечает драйвер и вся работа ложится на него.
Ну это мое мнение.
Все пробовал на NANO + три сдвиговых регистра.
Добрый день!
А куда вешается DS1307 и как вводиться дата?
У меня по I2C шине часики подключены.
Разбиваешь часики на константы (как часы, минуты, секунды) или просто из строки как из массива тянешь знак, ну и это все выкидываешь в функцию
void
Indicate(
int
r,
int
x). Правда дисплей у меня другой и разделителя нет в виде точек " : " . Пришлось использовать dp второго сигмента как
B11000000 == 0. Тоесть присваивание бита к int. B01000000 можите еще один массив с точками прописать. Как Вам угодно.У меня по I2C шине часики подключены.
Разбиваешь часики на константы (как часы, минуты, секунды) или просто из строки как из массива тянешь знак, ну и это все выкидываешь в функцию
void
Indicate(
int
r,
int
x). Правда дисплей у меня другой и разделителя нет в виде точек " : " . Пришлось использовать dp второго сигмента как
B11000000 == 0. Тоесть присваивание бита к int. B01000000 можите еще один массив с точками прописать. Как Вам угодно.как начальные значения времени вводятся. я смотрю все только на уровне бумаги делают, а в работе не идет. Время с потолка кажеться
Всю тему не осилил. К вопросу в первом посте две поправки: 1. shifhOut - выкинуть, он меделенный, 2. засветы развести за счет небольших задержек между гашением и включением катодов. Ниже код для часового секундомера с обратным отсчетом времени (с пищалкой) на примере Ардуино Мега и Attiny, в принципе подойдет для любого, главное чтобы все ножки SPI на одном порту были. Частота обновления кадров порядка тысячи-двух кадров в секунду.
Вариант выделенного "драйвера индикатора" на Attiny. Число передается по UART от внешнего источника, Тинька его принимает и крутит на индикаторе. Освобождает главный МК от необходимости делать это самостоятельно.
А вот вариант для секундомера на Attiny, катоды и аноды на ножках МК. Засвет идеально ровный за счет доводки таймингов по осциллографу.
Все скетчи рабочие, выдраны из готовых устройств.
Есть еще интересый вариант на базе специальной микросхемы TM1380, но это уже другая история.
Добрый день!
Может кто из местных гуру найдет ошибку в выводе информации на дисплей. 4-х битный 7-сегментный модуль на сдвиговых регистрах 595-х. В сериале все нормально работает показывает, а на дисплей переменные не выводит. Константы выводит нормально.
Что я Вам могу посоветовать. Вот накидал код, проверил. ПРАВДА я не стал циклом перебор выводимого "числа" делать, а просто определил место вывода. Все работает. НО! у меня дисплей немного не как у Вас. Смысл главное.
А что это за дисплей
Доброго дня. На самом деле, дисплей может быть любой, код универсален. Так, что для динамичекой индикации можно брать все, что угодно.
Вот, что получилось в итоге.
CheBuraw,
спасибо Вам за идею и тему, удалось подключить выпяный из старого сломанного DVD экранчик, работает зараза! Пришлось потанцевать, но все получилось, очень помогли Ваши коментарии в скетче.
Всем, кто приложил руки, к окончательному варианту, так же огромное спасибо!
Подскажите, как подключить 8 индикаторов, и вывести на них 2 переменные. 4 и 4.
Как вывести - читайте выше #125.
как подключить - последовательно, это же динамическая индикация, выше все описано. Схема стандартная. Разницы нет сколько сигментов используете. Обычная математика. Увеличивается число управляемых элементов.
Вот, переделал на 12 вольт. Использовал датчики от охранных систем. Изменил твердотельные реле.
Белый шлейф - на индикатор, рядом с индикатором приклеены две микросхамки для индикации.
Черная колодка - подключается шлейф на клавиатуру.
Всем привет.
Завалялся у меня такой индикатор, решил подклчить в проект. Из этого примера решил сделать библиотеку. Раньше я ничем подобным не занимался, поэтому возникили сложности.
Назовем библиотеку Display7
Код для Display7.h
Код Display7.cpp
Ну и сам пример для проверки.
Выдает ошибку что функции в loop не заданы. Где прокол? Камнями не кидайте.
Ну и сам пример для проверки.
Выдает ошибку что функции в loop не заданы. Где прокол? Камнями не кидайте.
Вы прикидываетесь? Где определения
ledDigitDisplay();
и
Indicate();
?
Вы прикидываетесь? Где определения
ledDigitDisplay();
и
Indicate();
?
Они же в библиотеке. Все примеры создания библиотек что я нашел, делалилсь примерно так. Я по аналогии и сделал.
Как по вашему должен выглядить пример?
Вообще, на самом деле меня в первую очередь интересует, как в этом коде сделать так, чтобы полученное значение дисплей показывал скажем 5 секунд.
Т.е, пусть будет температура. Получил я значение 23.50 и мне нужно тображать его 5 секунд. Внезависимости от того, что температура за бортом изменилась.
Вообще, на самом деле меня в первую очередь интересует, как в этом коде сделать так, чтобы полученное значение дисплей показывал скажем 5 секунд.
Т.е, пусть будет температура. Получил я значение 23.50 и мне нужно тображать его 5 секунд. Внезависимости от того, что температура за бортом изменилась.
Я думаю стоит начать с изучения языка программирования и принципов программирования, потом читать ошибки и варнинги компилчтора, а потом вам нужен будет таймер.
Я думаю, что если нечего сказть, то следует помолчать.
Нет желание отвечать на четкий вопрос, нечего и клавиши напрягать.
Я думаю, что если нечего сказть, то следует помолчать.
Нет желание отвечать на четкий вопрос, нечего и клавиши напрягать.
Вопрос? Не смешите. У вас целая задача и вы хотите ее решения
. И более четкого не звучало. Вы не знаете как библу подключить и как пользоваться ее функциями. И начали с этого, а потом хотелки свистелки полетели. Изучите теорию.
Где целая задача?
Вопрос четкий
Как подключить библиотеку не знаю? С чего вы это взяли? Как сделать библиотеку - не знаю. Это да. Потому что ни разу не делал. Но этот вопрос в целом не актуальный, а актуальный по ссылке.
Еще раз, есть что сказать по сути моего вопроса?
PS. Эту библиотеку делал я на основе кода, а не подключал. В отличии от вас, я ее не спрашивал у автора кода, а попытался сделать сам. Делал я ее потому что надо решить вопрос продолжительного свечения результата. Но пока делал, понял что то что хочу не получится.
А не могли бы вы подсказать, как в вашем коде сделать настройку часов с кнопок?
Повторил ваш проект, все работает
А не могли бы вы подсказать, как в вашем коде сделать настройку часов с кнопок?
Повторил ваш проект, все работает
Спасибо, что все работает. Тут такое дело. Я перевел "ЭТО безобразие" на ESP8266. Через WIFI, по MQTT проще менять и подстраивать данные, часы то же. НО! Часы, как модуль, можно выкинуть, хотя идут почти точно. Данные времени можено брать из GOOGle. Давно хотел объединить все проекты в доме.
По кнопачкам и настройке часов. Поставте модуль WiFi или bluetooth, и по Tx/Rx гоняйте данные с телефона. Но лучше esp8266.
Спасибо, наверно так и сделаю
Добрый день!
Заказал вот такой дисплей для домашних часов/термометра/барометра.
Не нашел отдельного выхода для изменения яркости - можно как то реализовать регулировку?
Нашёл решение, отбой вопросу, придут модули - буду пробовать
Отвечаю сам себе: реализовал подобие ШИМ с 7 сегментным индикатором,
выкладываю скетч часов/термометра/барометра - может кому пригодиться
Всем привет ! Такой вопрос как выводить с помощью вашего скетч значение переменной на экран. Например показание с потенцыометра ?
Заполнить нужными цифрами буфер в 46 строке скетч из 144 сообщения.
Всем привет пытаюсь подключить 6 сегментный индикатор на двух сдвиговых регистрах . Но работает только три сегмента и первый сегмент дублирует третий . Тоесть например цыфра 36 выводится как 636. В чем причина подскажите ??
Всем привет пытаюсь подключить 6 сегментный индикатор на двух сдвиговых регистрах . Но работает только три сегмента и первый сегмент дублирует третий . Тоесть например цыфра 36 выводится как 636. В чем причина подскажите ??
За основу взят скетч с 47 сообщения.
6 сегментный индикатор на двух сдвиговых регистрах
что за чудо такое ? посмотреть бы
и хотелось бы увидеть ваш скетч измененный, а не основу скетча с 47 сообщения