Ну вот наконец добрался до Attiny85, все хотел чего-нибудь сделать на них. А тут коллеги решили с гальваническими покрытиями поиграться. Путем нехитрых доработок блок питания для светодиодных дисплеев на 5В 60А стал регулируемым. А вот контролировать такие токи нечем. Шунт на 75мВ при 50А в местных магазинах мы нашли, а вот головку к нему нет, а стоять считать чего там милливольты показывают на мультиметре- такое себе.
Ну вот такой проект на один вечер.

ATTINY85
Attiny85 является старшим контроллером из 8 ногой серии МК аттини. От своих собратьев Attiny25 и 45- отличается объемом памяти. У 25- 2кБ, у 45- 4кБ, у нашей 85 соответственно целых 8кБ памяти, та же история и с EEPROM и SRAM. Да что я рассказываю, смотрите сами:

В общем отличный представитель класса компактных 8 битных МК. Пригодится там где не нужны большая производительность и обилие портов.
Аттини у нас маленькая, значит и дисплей надо брать маленький. Выбор пал на 0.91 дюймовый OLED с разрешением 128х32, контроллер SSD1306. Дёшево, сердито, и у меня их есть целая куча. Есть у меня такое увлечение- попытаться уложится в плату размером с дисплей, если это конечно возможно. В этот раз получилось.
Схема

Тут ничего нового. Усилитель на ОУ, пара делителей с фильтрующими емкостями, и стандартная обвязка для SSD1306. Чтобы получить из 75мВ вменяемые для АЦП значения выбран коэффициент усиления 31, что дает нам 2.2В при 71мВ и токе 47.3А на шунте. После ОУ мы это значение пилим пополам. Опорное напряжение- внутреннее 1.1В. R3 и С2 выступают фильтром ВЧ, а так-же коллега подсказал что без такой цепочки можно легко спалить вход ОУ при резком скачке тока н�� шунте.
Второй канал АЦП заведен через делитель на 16, что позволяет измерять до 17.6В. Так-же присутствует емкость для подавления помех. Про линейный стабилизатор на 3.3В я думаю можно не рассказывать.
В конкретно моем случае особая точность не нужна, но вы конечно можете пересчитать делители и КУ ОУ и либо увеличить точность, либо расширить диапазоны пожертвовав первой. АЦП у нас, напомню, разрядностью всего 10 бит.
Плата
Плата нарисована односторонняя, под возможности ЛУТ. Дисплей на стороне компонентов, поверх них. Плата размером с дисплей, за его пределы выходят только контакты для пайки проводов.

Как вы можете заметить- все очень компактно получилось. Этому поспособствовали и несколько килограмм приехавших недавно резисторов и конденсаторов размера 0603, которые я 2 дня раскладывал по кассетницам, но это уже другая история) . Дорожки в основном 0.25.

Плата вытравлена старым добрым ЛУТом. Правда в правильной модификации. Для переноса нужно использовать восковую бумагу, ту что является подложкой для самоклеящихся пленок. Написал бы отдельную статью о методе, но описаний технологии ЛУТ в интернетах уже столько, что скорее не буду.


Прошивка
ПО написано в среде Arduino IDE. Ядро используется AttinyCore. Библиотека дисплея Tiny4kOLED плюс шрифты . И то и другое доступно как по ссылкам выше, так и из менеджера плат и менеджера библиотек при помощи поиска.

Прошивал через USBasp и прищепку. Настройки остались все стандартные, если можно так сказать. Внутреннее тактирование на 8мГц. Прошивка грубо демонстрационная, прошу тапками не кидать, когда-нибудь скоро возможно напишу нормальную. А пока вдруг кто-нибудь решит повторить- все в ваших руках. Память используется почти вся, почти вся на шрифты. Это как первая цель для оптимизации. Еще парой строк можно добавить измерение мощности. Ну в общем есть где разгуляться.
Код
#include <Tiny4kOLED.h>
#include "ModernDos.h"
#include "ModernDos8.h"
#include "5x5_font.h"
int ADCV;
int ADCV1;
int ADCA;
int ADCA1;
float VOLT;
float AMP;
bool CH;
long MS;
//------------------------------------------------------------------------------
void setup() {
analogReference(INTERNAL1V1); //Устанавливаем опорное напряжение для АЦП- внутренее 1.1В
Wire.begin();
Wire.setClock(400000L);
oled.begin();
oled.clear();
oled.on();
}
//------------------------------------------------------------------------------
void loop() {
ADCV = analogRead(PB3) * 0.985; //Читае�� 3 канал АЦП и калибруем
ADCA = analogRead(PB4); //Читаем 2 канал
/*
Дальше идет конструкция с флагами чтобы не тратить ресурсы на обновление дисплея если нет изменений.
*/
if (ADCV1 != ADCV) { //Если резервное значение не равно значению с АЦП
ADCV1 = ADCV; //Записать в резервное значение новое значение АЦП
CH = 1; //Поднимаем флаг означающий новые данные
VOLT = float(map(ADCV, 0, 1023, 0, 1760)) / 100; //Стандартной функцией приводим значение из диапазона АЦП в диапазон нужный нам. Все это безобразие конверуем во Float и делим до реального значения.
}
if (ADCA1 != ADCA) {
ADCA1 = ADCA;
CH = 1;
AMP = float(map(ADCA, 0, 1023, 0, 47333)) / 1000;
}
if (CH && millis() > MS + 200) { //Если произошло изменение в данных, но не чаще 200мС, запускаем отрисовку данных на дисплей
MS = millis();
oled.setFontX2(FONT8X16MDOS);
oled.setCursor(0, 0);
oled.print(AMP, 1);
oled.setFontX2(FONT8X8MDOS);
oled.setCursor(64, 0);
oled.print("<A");
oled.setFontX2(FONT5X5);
oled.setCursor(64, 2);
oled.print(VOLT, 2);
oled.print("V");
CH = 0; //Сбрасываем флаг как только все сделано
}
}Файлы
Исходники на гитхаб. Схема и печатная плата в DipTrace.
Забавный факт. Когда рендерил 3D вид- вдруг пришла мысль что плата на что-то похожа. А похожа она на плату от USB флешки, или на тот же Digispark в варианте что втыкается в USB. Приложил плату от флешки и понял что по ширине они практически одинаковы. Но я так думаю что человек способный такую плату изготовить не додумается ее сунуть в USB.
А еще ко мне приехало некоторое количество Attiny10. Так что будет продолжение с еще более мелким устройством и уже точно нормальным кодом. Правда я так и не придумал что это будет. Предлагайте в комментариях.
UPD: Продолжение на Attiny10
