Универсальный Ардуино пробник

le8a
Offline
Зарегистрирован: 04.07.2019

Доброго времени суток!я прочитал все страницы ,по сути пробник находится всё ещё в стадии разработки т.е. нет файлов для повторения? ну скажем плата,схема,прошивка?

Xumuk
Xumuk аватар
Offline
Зарегистрирован: 03.03.2016

ну тут 2 варианта пробника от автора и еще одного человека, автор я так понял больше этим не занимается, а вот второй человек пропал=)

svm
Offline
Зарегистрирован: 06.11.2016

le8a пишет:

Доброго времени суток!я прочитал все страницы ,по сути пробник находится всё ещё в стадии разработки т.е. нет файлов для повторения? ну скажем плата,схема,прошивка?

Почему в разработке? Начиная с 183 поста показана готовая конструкция. Платы как таковой нет-используется про-мини. На нее напаяны несколько проводков и резисторов (видно на фото). Скетч под ОЛЕД дисплей есть, а "схема" вернее ее подобие из 25 поста. Первый вариант (с 30 поста) вообще на голой 328 навесным монтажем с семисегментными индикаторами.

 В принципе пока меня данный вариант устраивает, кроме габаритов (немного неудобно в руке). Заниматься пока некогда, хотя в планах есть задумка добавить грубое измерение емкости и ESR электролитов. Но в этот корпус наверное запихнуть не удастся.

le8a
Offline
Зарегистрирован: 04.07.2019

Спасибо, разобрался!

le8a
Offline
Зарегистрирован: 04.07.2019

думаю кое что полезного можно подчерпнуть отсюда:http://aelectrik.ru/svoimi-rukami/samaya-krutaya-kontrolka-avtoyelektri/

deemchik
Offline
Зарегистрирован: 29.07.2019

ребят! (пишу с вирт.клавы). тема клас! пару дней пробежался... по "свободке", штудирую подобные темы... в общем, многое для себя, нетолько открыл, но, и почерпал! познАвательного! svm и Andry Smart СПС! 

пы-сы (фонт ожырел :), избавиться не удается). Мне кажется, мой опыт в амбедЫнге (мк-быкодЫнг ) не лучше Вашего, и как-то тяжко арду-скотчи переваривать, проще си - там скотчя нет :). НО! БлагоДаря Вашим эксперементам... в общем (тоже) собираю мозг до кучи, для другого надеюсь, интересного проэкта. а стмка32 ну очень перспективнее. и не стесняйтесь пробовать ;), там тоже как с мегой/ардуниной, нужно только шагнуть. И примеров в сети... ну сами... Так, о чем я. ткните пинцетом пж-ста, на другие Ваши темы. Мой интерес прост (Задолбали мультиметры! "Хочу другой"! ) Не мои слова... :) А вот функционал, добавить хочеться :). во наболтал :)

Andry Smart
Offline
Зарегистрирован: 06.09.2016

да не пропал я. просто работы много а времени мало

еле склепал пробный образец

Xumuk
Xumuk аватар
Offline
Зарегистрирован: 03.03.2016

неплохо смотрится=)) а че умеет?)

Andry Smart
Offline
Зарегистрирован: 06.09.2016

пока работает как осциллограф с двумя входными делителями.

0-5v  и 0-20v  практически функционал пультоскопа. (кроме генератора и остальных фич)

переключается на лету кнопкой

 

как пробник пока не доброался сделать.

на данный момент меня не устраивает точность измерения. как по мне слабовато. решил сделать внешнее опорное на TL431  (2,5v)

 

Andry Smart
Offline
Зарегистрирован: 06.09.2016

Andry Smart
Offline
Зарегистрирован: 06.09.2016

svm
Offline
Зарегистрирован: 06.11.2016

Andry Smart пишет:

на данный момент меня не устраивает точность измерения. как по мне слабовато. решил сделать внешнее опорное на TL431  (2,5v)

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

На данный момент, добавил в пробник измерение конденсаторов от 0,001 до 2000 мкф.

Коротко с чего началось. Попался корейский кассовый аппарат, а в нем шикарный БП. +-12 В 2А. 5В 5А, 3,3В 5А, 30В 0,5А и все в габаритах 100х130 мм. Грех не использовать. Присобачил к нему китайский регулируемый STEP DOWN преобразователь. Получился регулируемый выход 1,5-10 В. В качестве корпуса идеально подошел корпус от российского кассового аппарата ШТРИХ-М. У него достаточно большой семисегментный дисплей, его-то и решил использовать для индикации напряжения БП. За основу была взята слегка поджаренная 168. Ну а дальше задушила жаба. Столько выводов, а используются только 4. Чтобы не мудрить взял скетч от пробника, выкинул автоматический режим и добавил режим измерения емкостей. Разбит на 2 поддиапазона. 0,001-150 мкф (с отдельным входом) измеряет достаточно точно и второй 0,5-2000 мкф погрубее, но определить высохший электролит труда не составляет. Переключение режимов последовательно одной кнопкой U-R-c-C-F . Далее снова режим измерения напряжения регулируемого БП. Переключение коротким нажатием с звуковой индикацией 2 КГц 50 мс. Длительное нажатие-выход на БП с сигналом 4 КГц 200 мс. Скетч написан достаточно криво, много разных костылей (в основном из-за нестандартного индикатора). Но память еще есть и оптимизировать лень. Если у кого-то найдется такой индикатор, то можно применять без изменений. Все три файла должны быть в одной папке.  По изменению назначения пинов D5,D6,D7 - менять нельзя. Остальные по желанию.

Основной скетч:


/*  Распайка индикатора STC030801DLGY-E-LM от ККМ "ЭЛВЕС-МИКРО"
 *1  Gnd                              Команды библиотеки
 *2  +5 V                             begin()       инициализация
 *3  Ddat                             clear_all()   очистка дисплея
 *4  Clk                              Ton()         звук 2 кГц 50 мс
 *5  CHARGE   зеленый светодиод       Ton_4()       звук 4 кГц 200 мс            
 *6  ACCLO    красный светодиод       Light_ON()      включить подсветку
 *7  DRes                             Light_OFF()     выключить подсветку 
 *8  +5 V                             OUT(a,b,c,d)    выести в позицию а,
 *9  NC                               число b, запятая отделяет с разрядов
 *10 NC                               d 4 или 2 - двоеточие */
#include "ELVES.h"
ELVES tablo(18,19,8); // DDAT,CLK,DRES   согласно схемы ККМ "ЭЛВЕС-МИКРО"
byte dot,dd,ri,svet,rr,kor;
byte simv_razr[8];// массив разрядов индикатора
long adc_buff,tau_svet,t_svet,t_delay;
float u_del,u_izm;
volatile unsigned int int_tic=0; 
volatile unsigned long tic; 
#define Red_Led 9            // Светодиод режимов
#define Btn 10               // кнопка режимов
//******************** Большие емкости **************************************
#define resistorValue  5500.0F   // Зарядный резистор для измерения емкости
//unsigned long startTime;
unsigned long elapsedTime;
float microFarads;                
float nanoFarads;
//********************* малые емкости ******************************************
const byte pulsePin = 13;                 //Пин подачи напряжения заряда 
const unsigned long resistance = 9100;   //Сопротивление зарядной цепи (9.1 KOm)
volatile boolean triggered;
volatile boolean active;
volatile unsigned long startTime;
volatile unsigned long rez,duration;

// Обработчик прерывания аналогового компаратора
ISR (ANALOG_COMP_vect)
  {
  unsigned long now = micros ();
  if (active)
    {
    duration = now - startTime;
    triggered = true;
    digitalWrite (pulsePin, LOW); // Снимаем напряжение заряда
    }
  }

//*****************************************************************************
void setup() {
Serial.begin(9600);
  tablo.begin();
  tablo.Light_ON();
  tablo.Ton_4();
  tablo.clear_all();
pinMode(Btn, INPUT);          // кнопка режимов
digitalWrite(Btn,1);          // включить подтягивающий резистор
pinMode(Red_Led, OUTPUT);     // Cветодиод включения пробника
//********************* малые емкости ******************************************
pinMode(pulsePin, OUTPUT);
  digitalWrite(pulsePin, LOW);
  Serial.println("Started.");
  //                       Настраиваем компаратор
  ADCSRB = 0;                        
  ACSR =  _BV (ACI)                   //флаг прерывания.  Устанавливается по событию,сбрасывается после ухода на обработчик либо программно, записью в него 1.
        | _BV (ACIE)                  //бит разрешения прерывания от компаратора.
        | _BV (ACIS0) | _BV (ACIS1); 
}
//********************************************************************************
void loop()
 {
Dialog(600);  // Опрос состояния кнопки или просто задержка в миллисекундах
//****************************************************************************
kor=0;                         //К-во доп. разрядов индикатора
if (ri==0){                    //Режим БП
   BP_voltmeter();             //Читаем напряжение Блока питания
   dot=2;                      //положение десятичной точки
   Chow_disp();                //вывод на дисплей
   tablo.OUT(7,15,dot,dd);     //вывод на дисплей буквы U в начале (FucrAU  10-15)
}//*****************************************************************************
 //Вольтметр
  if (ri==1){voltmeter();
   Chow_disp();                //вывод на дисплей
   tablo.OUT(7,11,dot,dd);     //вывод на дисплей буквы U в начале 
 }
//Омметр
 if (ri==2){ommeter();
   Chow_disp();                //вывод на дисплей
   tablo.OUT(7,13,dot,dd);     //вывод на дисплей буквы r в начале
 }
// Измерение емкостей 0,001-150 Мкф 
 if (ri==3){ C_meter_NF();
 if(rez>0){Chow_disp();}
 tablo.OUT(7,12,dot,dd);     //вывод на дисплей буквы c в начале 
 }
//Измерение емкости 0,5-500 Мкф
if (ri==4){ 
  pinMode(3, INPUT);
  pinMode(4, INPUT);
  pinMode(5, OUTPUT);     
  digitalWrite(5, LOW); 
  C_meter();
  Chow_disp();
 tablo.OUT(7,16,dot,dd);     //вывод на дисплей буквы C в начале
 }
 //Частотомер  
   if (ri==5){f_meter();
   Chow_disp();                //вывод на дисплей
   tablo.OUT(7,10,dot,dd);     //вывод на дисплей буквы F в начале
  }
  }
//----------------------  Конец лупа  -----------------------------------------


//****************************************************************************************
//                вывод на дисплей массива индикатора 
void Chow_disp()       
{ rez_mass();  //преобразуем число в массив символов разрядов индикатора
  tablo.clear_all();
  byte i=0;while(rez > 0){rez/=10;i++;} // Считаем к-во разрядов в числе
  i=i+kor;// Коррекция количества выводимых разрядов, если впереди нужны нули
  for (byte j=0;j<i;j++){tablo.OUT(j,(simv_razr[j]),dot,dd);} 
  }
//************ преобразуем число в массив символов разрядов индикатора *******************
void rez_mass(){
simv_razr[0]=(rez%10);
simv_razr[1]=(rez%100/10);
simv_razr[2]=(rez%1000/100);
simv_razr[3]=(rez%10000/1000);
simv_razr[4]=(rez%100000/10000);
simv_razr[5]=(rez%1000000/100000);
simv_razr[6]=(rez%10000000/1000000);
simv_razr[7]=(rez%100000000/10000000);
}

//               ---------  ПРОЦЕДУРЫ ИЗМЕРЕНИЯ  --------

void voltmeter(){// *************** ВОЛЬТМЕТР *****************
analogReference(INTERNAL);// включаем внутренний ИОН 1.1 В
pinMode(2, INPUT); 
pinMode(3, INPUT); 
pinMode(4, OUTPUT); // выводим на 4 пин 0
digitalWrite(4,0);         // устанавливая его в 0(включаем нижний резистор делителя)
  delay(2);
adc_buff=0;
for (int n=0; n<=255; n++ ) {
adc_buff+= analogRead(A1); }
adc_buff >>=4; // 16368 полная шкала 14bit
rez= (float)adc_buff/16368.0*1135;// - реальный коэфф делителя
}
//**********************************************************************
//вольтметр контроля БП
void BP_voltmeter(){
analogReference(INTERNAL);// включаем внутренний ИОН 1.1 В
delay(2);
adc_buff=0;
for (int n=0; n<=255; n++ ) {
adc_buff+= analogRead(A0); }
adc_buff >>=4; // 16368 полная шкала 14bit
rez= (float)adc_buff/16368.0*1135;// - реальный коэфф делителя
}
//********************************************************************************
void Dialog(long t_zad){       // Выбор режимов или просто задержка
svet=0;t_delay=millis();
Button:                  
if ((millis()-t_delay)>t_zad)goto WD;    //Время задержки
if (digitalRead(Btn)==0 && svet==0){t_svet=millis();svet=1;goto Button;}
if (digitalRead(Btn)==0 && svet==1){t_delay=millis();goto Button;}
if (digitalRead(Btn)==1 && svet==1){tau_svet=millis()-t_svet;
if (tau_svet<400 && tau_svet>50){ri++;tablo.Ton();} //короткое нажатие выбор № режима 
if (tau_svet>500){ri=0;tablo.Ton_4();}                //длинное  нажатие режим № 0
if (ri>=6)ri=0;                         //Ограничение к-ва режимов
if (ri==0)digitalWrite(Red_Led,LOW);    // выключить красный светодиод
if (ri>0)digitalWrite(Red_Led,HIGH);    // включить красный светодиод
svet=0;t_svet=0;goto WD;}
goto Button;
WD:
delay(2);
}
void f_meter(){//************** ЧАСТОТОМЕР ********************
pinMode(4, OUTPUT);                   // выводим на 4 пин 0
digitalWrite(4,0);                    // загрубляем вход (борьба с наводками)
//pinMode(4, INPUT);                  // если нужна макс. чувствительность
pinMode (5,INPUT);                    // вход сигнала T1 (для atmega168/328)
int_tic=0; TCNT1 = 0;
TCCR1B =(1<<CS10)|(1<<CS11)|(1<<CS12);//тактировани от входа Т1
delay(1000);                          // Время измерения
TCCR1B=0;
tic= ((uint32_t)int_tic<<16) | TCNT1; //сложить что натикало
rez=tic;
}
//****************************************************************************
void ommeter(){// *************** ОММЕТР *****************
 rr=1;dot=1;    
pinMode(2, INPUT);         // 2 пин высокий импеданс
pinMode(3, INPUT);         // 3 пин высокий импеданс
pinMode(4, OUTPUT);        // 4 пин выход
digitalWrite(4,1);         // переводим его в 1 подключаем измерительный резистор 20 kOm
analogReference(DEFAULT);  // подключаем опорное 5 В  
delay(2);
// измеряем полное напряжение на делителе под нагрузкой
//**************************************************************
adc_buff=0;
for (int n=0; n<=255; n++ ) {
adc_buff+= analogRead(A1); }
adc_buff >>=4;
u_del= (float)adc_buff;
// измеряем напряжение на измеряемом резисторе
//**************************************************************
adc_buff=0;
for (int n=0; n<=255; n++ ) {
adc_buff+= analogRead(A3); }
adc_buff >>=4;
u_izm= (float)adc_buff;
rez= float(u_izm*4600)/float(u_del-u_izm);// для 4.6 kOm
if (u_izm>4000){;//Если значение достоверно - вывод на индикацию
rez/=10;dot=1;
goto vyv;
}
//#############################  4,7 kOm  ######################################
rr=2;
pinMode(4, INPUT);         // 4 пин высокий импеданс
pinMode(3, OUTPUT);        // 3 пин выход
digitalWrite(3,1);         // переводим его в 1 подключаем измерительный резистор 4.7 kOm
analogReference(DEFAULT);// подключаем опорное 5 В  
delay(2);
// измеряем полное напряжение на делителе под нагрузкой
//**************************************************************
adc_buff=0;
for (int n=0; n<=255; n++ ) {
adc_buff+= analogRead(A2); }
adc_buff >>=4;
u_del= (float)adc_buff;
// измеряем напряжение на измеряемом резисторе
//**************************************************************
adc_buff=0;
for (int n=0; n<=255; n++ ) {
adc_buff+= analogRead(A1); }
adc_buff >>=4;
u_izm= (float)adc_buff;
rez= float(u_izm*4750)/float(u_del-u_izm);// для 4,7 kOm
if (u_izm>4000){;
goto vyv;
}
 //#############################  500 Om  ######################################
 rr=3;dot=0;
  analogReference(DEFAULT);// подключаем опорное 5 В
pinMode(3, INPUT);         // 3 пин высокий импеданс
pinMode(2, OUTPUT);        // 2 пин выход
digitalWrite(2,1);         // переводим его в 1 подключаем измерительный резистор 500 Ом 
  delay(2);
// измеряем полное напряжение на делителе под нагрузкой
//**************************************************************
adc_buff=0;
for (int n=0; n<=255; n++ ) {
adc_buff+= analogRead(A3); }
adc_buff >>=4; 
u_del= (float)adc_buff;
// измеряем напряжение на измеряемом резисторе
//**************************************************************
// сначала при опорном 5 В
adc_buff=0;
for (int n=0; n<=255; n++ ) {
adc_buff+= analogRead(A1); }
adc_buff >>=4;
 u_izm= (float)adc_buff;
rez= float(u_izm*460)/float(u_del-u_izm);// для 460 om
//rez/=10;dot=1;
if (u_izm >4000){
goto vyv;
}
//Если  точность не удовлетворяет переходим на опорное 1,1 В
// измеряем полное напряжение на делителе под нагрузкой при опорном 5 В
//**************************************************************
rr=4;dot=0;
adc_buff=0;
for (int n=0; n<=255; n++ ) {
adc_buff+= analogRead(A3); }
adc_buff >>=4;
u_del= (float)adc_buff/16368*(float)readVcc();
// измеряем напряжение на измеряемом резисторе
analogReference(INTERNAL);// подключаем опорное 1.1 В
delay(2);
adc_buff=0;
for (int n=0; n<=255; n++ ) {
adc_buff+= analogRead(A1); }
adc_buff >>=4; 
u_izm= (float)adc_buff/16368*1100;
(rez)= float(u_izm*500)/float(u_del-u_izm);
vyv:;
if (rez>100000){rez=0;dot=0;}
}
//********************* измерение напряжения питания ****************************
long readVcc() {
  ADMUX = _BV(REFS0) | _BV(MUX3) | _BV(MUX2) | _BV(MUX1);
  delay(2); // Wait for Vref to settle
  ADCSRA |= _BV(ADSC); // Convert
  while (bit_is_set(ADCSRA,ADSC));
  uint8_t low = ADCL; // сначала нужно прочесть ADCL - это запирает ADCH
  uint8_t high = ADCH; // разлочить оба
  float result = (high<<8) | low;
  //result = (1.03357 * 1023.0*1000) / result;
  result =1057342.11/ result;
  return result;
}
//****************** Измерение емкости 0,001-150 Мкф ****************************
// Взято из http://digitrode.ru/computing-devices/mcu_cpu/816-izmeritel-emkosti-na-arduino-svoimi-rukami.html
void C_meter_NF()
{
  if (!active)
    {
    active = true;
    triggered = false;
    digitalWrite (pulsePin, HIGH);   // Включаем напряжение заряда
    startTime = micros ();  
    }
  if (active && triggered)
    {
    active = false;
    rez= (duration * 1000/ resistance);dot=3;kor=0;    //Готовим результат для вывода
    if (rez>150000)rez=0;// Оптимизация ирдикации
    if (rez<1000)kor=1;
    if (rez<100)kor=2;
    if (rez<10)kor=3;
    triggered = false;
    delay (1000);
 }}
//****************** Измерение емкости 0,5-500 Мкф ********************************************
// Взято из http://digitrode.ru/computing-devices/mcu_cpu/816-izmeritel-emkosti-na-arduino-svoimi-rukami.html
void C_meter(){
  digitalWrite(5, HIGH);              //Включаем заряд конденсатора
  startTime = millis();               //Засекаем время
  while(analogRead(A2) < 648){}       //Ждем пока конденсатор не зарядится до 63,2% или 1,58 от  полной зарядки
  elapsedTime= millis() - startTime;  //Фиксируем время заряда
  if (elapsedTime<2)elapsedTime=0;    // Борьба с шумами
  microFarads = ((float)elapsedTime / resistorValue) * 1000;  
  if (microFarads > 1){
  rez=microFarads*100;dot=2;kor=0;    //Готовим результат для вывода
    }
  else{
    nanoFarads = microFarads * 1000;      
    rez=microFarads*10;dot=1;kor=1;   //Готовим результат для вывода
    delay(500);}
  digitalWrite(5, LOW);               //Снимаем напряжение           
  pinMode(2, OUTPUT);                 //Разряжаем кондюк         
  digitalWrite(2, LOW);               //Закорачивая его на землю
  while(analogRead(A2) > 0){}         // Пока не разрядится         
  pinMode(2, INPUT);                  // Отключаем разряд 
} 

 

ELVES.h




#ifndef _ELVES_h
#define _ELVES_h

#if ARDUINO >= 100
#include "Arduino.h"
#else
#include "WProgram.h"
#endif

#define TAKE_CS()    digitalWrite(_CS_pin, LOW)
#define RELEASE_CS() digitalWrite(_CS_pin, HIGH)

class ELVES {
  private:
    uint8_t _DATA_pin;
    uint8_t _RW_pin;
    uint8_t _CS_pin;

  protected:

  public:

    enum Modes : uint8_t {
      COMMAND_MODE = 0b1000, /*!< This is used for sending standard commands. */
      WRITE_MODE = 0b1010, /*!< This instructs the ELVES to prepare for writing the internal RAM. */
      };

    ELVES(uint8_t DATApin, uint8_t RWpin, uint8_t CSpin) : _CS_pin(CSpin), _DATA_pin(DATApin), _RW_pin(RWpin) {};
   
    void begin(void);
  // Очистить память
    void clear_all();
// зажечь в разряде (razr) цифру (dat) , запятая отделяет (dot) последних знаков,dd двоеточие
void OUT(int razr,int dat,int dot,int dd);
 
    void Ton();
    void Ton_4();
    void Light_ON();
    void Light_OFF();
        
   // последовательность битов (в количестве (сnt)) отсылается по текущему адресу 
    void writeBits(uint8_t data, uint8_t cnt);
    
    // посылает ID команды (CS не контролируется
    void sendCommand(uint8_t cmd);
    
    //по адресу (address)запись байта (data)
    void write(uint8_t address, uint8_t data);
      
    //по адресу (address)запись байта (data) по (cnt) последовательным адресам.
    void write_c(uint8_t address, uint8_t data, uint8_t cnt);   
   
    //с адреса (address)запись (cnt) байтов (data) 
    void write(uint8_t address, uint8_t *data, uint8_t cnt);
 };   
#endif

ELVES.cpp

/**
   \file ELVES.cpp
   \\author Enrico Formenti
   \date 31 january 2015
   \version 1.0
*/

#include "ELVES.h"

byte pos[8][3]={
11,9,10,    //   0 разряд
13,8,12,    //
15,7,14,    //
17,6,16,    //
19,5,18,    //
3,4,20,     //   5
0,1, 2,     //   6
22,21,0     //   7 разряд
};
byte simv[51][3]={// знакогенератор 1-х пяти разрядов
12,10,12,   //0
0,0,12,     //1
4,14,8,     //2
0,14,12,    //3
8,4,12,     //4
8,14,4,     //5
12,14,4,    //6
0,8,12,     //7
12,14,12,   //8
8,14,12,    //9  
//  5-6 разряды
4,10,14,    //0
0,0,6,      //1
4,6,12,     //2
0,6,14,     //3
0,12,6,     //4
0,14,10,    //5
4,14,10,    //6
0,0,14,     //7
4,14,14,    //8
0,14,14,    //9

//     7 разряд
8,12,8,     //0 неполноценный болше похож на значек градуса
0,2,8,      //1
6,12,8,     //2
2,14,8,     //3
8,6,8,      //4
10,14,0,    //5
14,14,0,    //6
0,10,8,     //7
14,14,8,    //8
10,14,8,    //9
12,12,0,    //F  10
6,2,0,      //u  11 
6,4,0,      //c  12
4,4,0,      //r  13
12,14,8,    //A  14
14,2,8,     //U  15
14,8,0,     //C  16
};

void ELVES::begin()
{
  pinMode(_DATA_pin, OUTPUT);
  pinMode(_RW_pin, OUTPUT);
  pinMode(_CS_pin, OUTPUT);
  digitalWrite(_CS_pin, HIGH);
  digitalWrite(_RW_pin, HIGH);
  digitalWrite(_DATA_pin, HIGH);
  sendCommand(0b00011000);//RC256K
  sendCommand(0b00101000);//BIAS_THIRD_3_COM
  sendCommand(0b00000001);//SYS_EN
  delay (250);
  sendCommand(3);//LCD_ON
 }

void ELVES::writeBits(uint8_t data, uint8_t cnt)
{
  for (register uint8_t i = 0; i < cnt; i++, data <<= 1)
  {
  pinMode(_DATA_pin, OUTPUT);
  digitalWrite(_RW_pin, LOW);
   delayMicroseconds(25);//  после клика

    switch (cnt)
    {
      case 4:
        digitalWrite(_DATA_pin, data & 0x8 ? HIGH : LOW);
        break;
      case 5:
        digitalWrite(_DATA_pin, data & 0x10 ? HIGH : LOW);
        break;
      case 8:
        digitalWrite(_DATA_pin, data & 0x80 ? HIGH : LOW);
        break;
    }
     delayMicroseconds(25);// Длительность данных
    digitalWrite(_RW_pin, HIGH);
     delayMicroseconds(25); // длительность клика
  }
}

void ELVES::sendCommand(uint8_t cmd)
{
  TAKE_CS();
   digitalWrite(_DATA_pin, HIGH);
   delayMicroseconds(25);//
   digitalWrite(_RW_pin, HIGH);//
   delayMicroseconds(25);//
   digitalWrite(_RW_pin, LOW);//
   digitalWrite(_DATA_pin, LOW);

   delayMicroseconds(25);//
   digitalWrite(_RW_pin, HIGH);//
   delayMicroseconds(25);//
   digitalWrite(_RW_pin, LOW);//

   delayMicroseconds(25);//
   digitalWrite(_RW_pin, HIGH);//
   delayMicroseconds(25);//
   digitalWrite(_RW_pin, LOW);//
   
  ELVES::writeBits(cmd, 8);
  digitalWrite(_RW_pin, LOW);
  delayMicroseconds(25);//
  digitalWrite(_RW_pin, HIGH);//
  delayMicroseconds(25);//
  digitalWrite(_RW_pin, LOW);//

  delayMicroseconds(25);//
  RELEASE_CS();
  delayMicroseconds(25);
}
void ELVES::write(uint8_t address, uint8_t data)
{
  TAKE_CS();
  ELVES::writeBits(WRITE_MODE, 4);
  ELVES::writeBits(address, 5);
  ELVES::writeBits(data, 4);
                 digitalWrite(_RW_pin, LOW);
                  delayMicroseconds(25);
                 digitalWrite(_DATA_pin, LOW);
  RELEASE_CS();
                  delayMicroseconds(25);
}

void ELVES::write_c(uint8_t address, uint8_t data, uint8_t cnt)
{
  TAKE_CS();
  ELVES::writeBits(WRITE_MODE, 4);
  ELVES::writeBits(address, 5);
  for (register uint8_t i = 0; i < cnt; i++)
  {
    ELVES::writeBits(data, 4);
  }
      digitalWrite(_RW_pin, LOW);
                  delayMicroseconds(25);
                 digitalWrite(_DATA_pin, LOW);
  RELEASE_CS();
                  delayMicroseconds(25);
}

void ELVES::write(uint8_t address, uint8_t *data, uint8_t cnt)
{
  TAKE_CS();
  ELVES::writeBits(WRITE_MODE, 4);
  ELVES::writeBits(address, 5);
  for (register uint8_t i = 0; i < cnt; i++)
  {
    ELVES::writeBits(data[address + i], 4);
  }
      digitalWrite(_RW_pin, LOW);
                  delayMicroseconds(25);
                 digitalWrite(_DATA_pin, LOW);
  RELEASE_CS();
                  delayMicroseconds(25);
}

void ELVES::clear_all()
{
  ELVES::write_c(0, 0, 32);
}


void ELVES::Ton()
{
  sendCommand(0b01100000);//TONE2K
  sendCommand(0b00001001);//TONE_ON
  delay (50);
  sendCommand(0b00001000);//TONE_OFF
}

void ELVES::Ton_4()
{
  sendCommand(0b01000000);//TONE4K
  sendCommand(0b00001001);//TONE_ON
  delay (200);
  sendCommand(0b00001000);//TONE_OFF
}

void ELVES::Light_ON()
{
  sendCommand(0b10001000);//IRQ_EN
}

void ELVES::Light_OFF()
{
  sendCommand(0b10000000);//IRQ_DIS
}

void ELVES::OUT(int razr,int dat,int dot,int dd)        //разряд,число,количество знаков после запятой
{  int d=0;
int k=0;
   if (razr==dot-1)d=2;                   //Ставим точку
   if (razr==dd)k=2;
   if (razr>4)dat=dat+10;                 //Если разряд больше 4 переключаемся на 2 знакогенератор
   if (razr==7)dat=dat+10;                //Если разряд равен  7 переключаемся на 3 знакогенератор
   write_c(pos[razr][0],(simv[dat][0])+d,1);    //+2 точка перед цифрой 
   write_c(pos[razr][1],simv[dat][1],1);//
   write_c(pos[razr][2],(simv[dat][2])+k,1);    //+2 - двоеточие после и точка после 7 разр
}

Cхема:

Фото девайса:

Andry Smart
Offline
Зарегистрирован: 06.09.2016

а кто знает как ssd1306 переключать в спячку и возвращать обратно с библиотекой adafruit ?

Andry Smart
Offline
Зарегистрирован: 06.09.2016

на данній момент в проекте осталось только 4 кнопки.

1 подсветка фонарик

2 нагрузка (соединяет щуп с массой через лампу накаливания маленькую такую)

3 и 4 управление самим пробником. mode и set

 

пытаюсь убрать выключатель питания. мучаюсь с режимами энергосбережения.

еще мучаюсь с автопереключение делителя (для осциллографа) и авторазвертки.

весь этот процесс рождения новых идей мешает да и работаю 6 дней в неделю. машин много а времени мало.

вот как сделаю такого помощника то надеюсь времени будет больше.

по поводу опорного напряжения оставлю внутренний источник (а то на tl431 мешает реализации спящего режима) 

svm
Offline
Зарегистрирован: 06.11.2016
Добавил в пробник еще один режим - измерение емкостей от 0,1 до 500 мкФ. Отправной точкой 
 
 
 Первый режим вписался без проблем, только программная доработка. Недостаток - нельзя 
 
измерять емкости меньше 0,1 мкФ и длительное время измерения больших. Так 200 мкФ - около 10 
 
секунд. Если второй недостаток можно  победить, уменьшив номинал зарядного резистора, то первый 
 
ограничивает использование для измерения милисекунд.  Второй вариант позволяет измерять 
 
емкости от 1 нФ, но требует схемных изменений (установки делителя для подачи опорного 
 
напряжения на компаратор), что пока невозможно т.к. конструкция пробника (из-за необдуманного 
 
применения суперклея) не позволяет это оперативно сделать. Но на макете работает без проблем. 
 
Пример есть в конце темы http://arduino.ru/forum/programmirovanie/problema-s-komparatorom . Малые 
 
емкости (вариант 3) пока не понравились. Нет стабильности, возможно из-за длинных проводов и 
 
монтажа на соплях. Да и надобность в нем небольшая.
В схеме делитель опорного напряжения присутствует, но пока не используется. В другой конструкции - БП со встроенным пробником, работает адекватно.
 
Скетч нового варианта 
 


 // Входом частотомера является цифровой пин 5
 #include <Wire.h>
 #include "SSD1306Ascii.h"
 #include "SSD1306AsciiWire.h"
 #define I2C_ADDRESS 0x3C
 //#define DEBUG // Раскомментировать,если нужна отладочная информация в монитор
 SSD1306AsciiWire oled;
 //******************** Большие емкости **************************************
#define resistorValue  24500.0F   // Зарядный резистор для измерения емкости
unsigned long elapsedTime;
float microFarads;                
float nanoFarads;
volatile unsigned long startTime;
//volatile unsigned long rez,duration;
//**************************************************************************** 
 volatile unsigned int int_tic=0; 
 volatile unsigned long tic; 
 long adc_buff,tau_svet,t_svet;
 float u_del,u_izm,rez;
 byte ri,rr,rs,prob,svet;// режим измерения
//***************************************************************

void setup()
{
 Serial.begin(9600);
  #ifdef  DEBUG 
 Serial.begin(9600);
 #endif
 Wire.begin();
 Wire.setClock(400000L);
  oled.begin(&Adafruit128x32, I2C_ADDRESS);
  oled.setFont(font5x7);
  oled.clear();
  oled.set2X();
  tone(9,500,100);                   
  oled.println("  PROBNIK");
  delay(1000);
TCCR1A=0; TIMSK1 = 1<<TOIE1; //прерывание по переполнению
}
ISR (TIMER1_OVF_vect){ int_tic++;
}

void loop(){
rs=0;  
svet=0;
prob=1;
start:
pinMode(2, INPUT);// 2 пин высокий импеданс
pinMode(3, INPUT);// 3 пин высокий импеданс
pinMode(4, INPUT);// 4 пин высокий импеданс
//*******************************************************************
svet:// фиксация длительности вкючения кнопки подсветки
if (analogRead(A0)>100 && svet==0){t_svet=millis();svet=1;goto svet;}
if (analogRead(A0)>100 && svet==1)goto svet;
if (analogRead(A0)<10  && svet==1){tau_svet=millis()-t_svet;
if (tau_svet<400){rr++;prob=0;rs=0;} //короткое нажатие выбор режима
if (tau_svet>800){rr=0;prob=1;}      //очень длинное  нажатие возврат к пробнику
if (tau_svet>450)rr=0;               //длинное  нажатие
svet=0;t_svet=0;}
//************** измерение выборочных величин ************************

if (rr==0)goto probn;
if (rr==1){show_menu();voltmeter();}
if (rr==2){show_menu();ommeter();}
if (rr==3){show_menu();f_meter();ri=0;}
if (rr==4){show_menu();C_meter();}
if (rr>4){show_menu();goto probn;}
vdspl();
if (prob==0)goto start;


probn:;//******************** РЕЖИМ ПРОБНИКА ****************************
  
//****************************  ЧАСТОТОМЕР ******************************************
test_F();     //  Тест наличия импульсов с F>5 Гц.
if (tic>1) {  // Если есть импульсы измеряем частоту
f_meter();
goto ind;
}
//**************************** Вольтметр ******************************************
voltmeter();
if (adc_buff > 150) goto ind;   //если есть напряжения выводим - иначе измеряем сопротивление
//**************************** ОММЕТР ********************************************
//rezist:
ommeter();
//*************************** ИНДИКАЦИЯ ************************************
ind:;
vdspl();// Вывод на дисплей 
 #ifdef  DEBUG 
 info(); 
 #endif
goto start;
}
// ************* Конец лупа ***********************

void show_menu(){
if (rs==0){
tone(9,500,100);                   
oled.clear();
if (rr>4){oled.println("  PROBNIK");rr=0;}
if (rr==1)oled.println("  Voltmetr");
if (rr==2)oled.println("  Ommeter");
if (rr==3)oled.println("  F_meter");
if (rr==4){oled.println("  C_meter");
           oled.print  ("0.1-500 mF");}
delay(600);
rs=rr;}}


//**************************************************************************
// вывод на  SSD1306
void vdspl()
{ 
if (rez> 7999999 || rez<0){         //ХЗ что на входе
//oled.clear();
oled.setCursor(1,0);
oled.println(" Incorrect ");
oled.print(" data  R/");
if (rr==1) oled.print("U");
if (rr==2) oled.print("R");
if (rr==3) oled.print("F");
if (rr==4) oled.print("C");
if (rr==0) oled.print("P");
goto vdsp;
}  
oled.setCursor(1,0);
if (rez==0)goto vdsp;
if (ri==5 && rez >=0 && rez < 1){;   //Щупы 3акорочены или сопроивление < 1 Om
tone(9,500,100);                     // для пассивного спикера на 9 пине
oled.clear();
oled.println("  SHORT     ");
delay(100);
goto vdsp;
}
if (ri==0){ 
oled.print (int(rez));
oled.println("              ");
oled.print("HZ          ");
goto vdsp;
}
if (rs==3)goto vdsp;
if (ri==1){;                        // Вывод напряжения
oled.print(rez,2);
oled.println("           ");
oled.print("VOLTS   ");
goto vdsp;
}
if (ri==6){;                        // Вывод емкости
oled.print(rez,2);
oled.println("           ");
oled.print  ("MicroFarad");
goto vdsp;
}

if (ri==2 ||ri==3) rez=rez/1000;    // Вывод сопртивления
oled.print(rez,1);
oled.println("         ");
if (ri==2 ||ri==3) oled.println(" KOhm    ");  
else oled.println(" Ohm     ");                    
vdsp:; 
}


// измерение напряжения питания
long readVcc() {
  ADMUX = _BV(REFS0) | _BV(MUX3) | _BV(MUX2) | _BV(MUX1);
  delay(2); // Wait for Vref to settle
  ADCSRA |= _BV(ADSC); // Convert
  while (bit_is_set(ADCSRA,ADSC));
  uint8_t low = ADCL; // сначала нужно прочесть ADCL - это запирает ADCH
  uint8_t high = ADCH; // разлочить оба
  float result = (high<<8) | low;
  //result = (1.03357 * 1023.0*1000) / result;
  result =1057342.11/ result;
  return result;
}

//************* отладочная информация *****************
void info(){
Serial.println("-------<>-------");
Serial.println("");
Serial.print("REJIM - ");
Serial.println(ri);
Serial.print("UCC   = ");
Serial.print((float)readVcc());
Serial.println(" V");
Serial.print("U_del - ");
Serial.println(u_del);
Serial.print("U_izm - ");
Serial.println(u_izm);
Serial.print("REZULT- ");
Serial.println((float)rez);
Serial.println("");
Serial.println("-------<>-------");
delay(1500);
}


void voltmeter(){// *************** ВОЛЬТМЕТР *****************
   ri=1; 
 analogReference(INTERNAL);// включаем внутренний ИОН 1.1 В
pinMode(2, INPUT); 
pinMode(3, INPUT); 
pinMode(4, OUTPUT); // выводим на 4 пин 0
digitalWrite(4,0);         // устанавливая его в 0(включаем нижний резистор делителя)
  delay(2);
adc_buff=0;
for (int n=0; n<=255; n++ ) {
adc_buff+= analogRead(A1); }
adc_buff >>=4; // 16368 полная шкала 14bit
rez= (float)adc_buff/16368.0*5.29;// - реальный коэфф делителя
}
//****************************************************************************
void ommeter(){// *************** ОММЕТР *****************
     
//R=20 kOm  
ri=2;
pinMode(2, INPUT);         // 2 пин высокий импеданс
pinMode(3, INPUT);         // 3 пин высокий импеданс
pinMode(4, OUTPUT);        // 4 пин выход
digitalWrite(4,1);         // переводим его в 1 подключаем измерительный резистор 20 kOm
analogReference(DEFAULT);// подключаем опорное 5 В  
delay(2);

// измеряем полное напряжение на делителе под нагрузкой
//**************************************************************
adc_buff=0;
for (int n=0; n<=255; n++ ) {
adc_buff+= analogRead(A1); }
adc_buff >>=4;
u_del= (float)adc_buff;

// измеряем напряжение на измеряемом резисторе
//**************************************************************
adc_buff=0;
for (int n=0; n<=255; n++ ) {
adc_buff+= analogRead(A3); }
adc_buff >>=4;
u_izm= (float)adc_buff;
rez= float(u_izm*20000)/float(u_del-u_izm);// для 20 kOm
if (u_izm>4000){;//Если значение достоверно - вывод на индикацию
goto vyv;
}

//#############################  4,7 kOm  ######################################
ri=3;
pinMode(4, INPUT);         // 4 пин высокий импеданс
pinMode(3, OUTPUT);        // 3 пин выход
digitalWrite(3,1);         // переводим его в 1 подключаем измерительный резистор 4.7 kOm
analogReference(DEFAULT);// подключаем опорное 5 В  
delay(2);

// измеряем полное напряжение на делителе под нагрузкой
//**************************************************************
adc_buff=0;
for (int n=0; n<=255; n++ ) {
adc_buff+= analogRead(A2); }
adc_buff >>=4;
u_del= (float)adc_buff;

// измеряем напряжение на измеряемом резисторе
//**************************************************************
adc_buff=0;
for (int n=0; n<=255; n++ ) {
adc_buff+= analogRead(A1); }
adc_buff >>=4;
u_izm= (float)adc_buff;
rez= float(u_izm*4750)/float(u_del-u_izm);// для 4,7 kOm
if (u_izm>4000){;
goto vyv;
}

 //#############################  500 Om  ######################################
 
  analogReference(DEFAULT);// подключаем опорное 5 В
  ri=4;
pinMode(3, INPUT);         // 3 пин высокий импеданс
pinMode(2, OUTPUT);        // 2 пин выход
digitalWrite(2,1);         // переводим его в 1 подключаем измерительный резистор 500 Ом 
  delay(2);
// измеряем полное напряжение на делителе под нагрузкой
//**************************************************************
adc_buff=0;
for (int n=0; n<=255; n++ ) {
adc_buff+= analogRead(A3); }
adc_buff >>=4; 
u_del= (float)adc_buff;

// измеряем напряжение на измеряемом резисторе
//**************************************************************
// сначала при опорном 5 В
adc_buff=0;
for (int n=0; n<=255; n++ ) {
adc_buff+= analogRead(A1); }
adc_buff >>=4;
 u_izm= (float)adc_buff;
rez= float(u_izm*500)/float(u_del-u_izm);// для 500 om
if (u_izm >4000){
goto vyv;
}
//Если  точность не удовлетворяет переходим на опорное 1,1 В
// измеряем полное напряжение на делителе под нагрузкой при опорном 5 В
//**************************************************************
ri=5;
adc_buff=0;
for (int n=0; n<=255; n++ ) {
adc_buff+= analogRead(A3); }
adc_buff >>=4;
u_del= (float)adc_buff/16368*(float)readVcc();

// измеряем напряжение на измеряемом резисторе
analogReference(INTERNAL);// подключаем опорное 1.1 В
delay(2);
adc_buff=0;
for (int n=0; n<=255; n++ ) {
adc_buff+= analogRead(A1); }
adc_buff >>=4; 
u_izm= (float)adc_buff/16368*1100;
(rez)= float(u_izm*500)/float(u_del-u_izm);
vyv:;
}


void init_fm(){// ********* конфигурация входов частотомера *******
ri=0;
pinMode(4, OUTPUT);        // выводим на 4 пин 0
digitalWrite(4,0);         // загрубляем вход (борьба с наводками)
//pinMode(4, INPUT);       // если нужна макс. чувствительность
pinMode (5,INPUT);         // вход сигнала T1 (для atmega168/328)
}


void f_meter(){//*******************ЧАСТОТОМЕР********************
ri=0;
if (analogRead(A0)>100)rr=0;prob=1;goto vf;// ПРОВЕРКА КНОПКИ
init_fm();  
int_tic=0; TCNT1 = 0;
TCCR1B = (1<<CS10)|(1<<CS11)|(1<<CS12);//тактировани от входа Т1
delay(1000);// Время измерения
TCCR1B=0;
tic= ((uint32_t)int_tic<<16) | TCNT1; //сложить что натикало
rez=tic;
vf:;
}

void test_F(){// ******* Тест наличия импульсов с F>5 Гц.********
init_fm();
ri=0;
int_tic=0; TCNT1 = 0;
TCCR1B = (1<<CS10)|(1<<CS11)|(1<<CS12);//тактировани от входа Т1
delay(50);// Тестовый замер (срабатывает> 5 Гц  устойчиво)
TCCR1B=0;
tic= ((uint32_t)int_tic<<16) | TCNT1; //сложить что натикало
rez=tic;
}
//****************** Измерение емкости 0,1-500 Мкф ********************************************
// Взято из http://digitrode.ru/computing-devices/mcu_cpu/816-izmeritel-emkosti-na-arduino-svoimi-rukami.html
void C_meter(){
  ri=6;
  pinMode(2, INPUT);
  pinMode(3, INPUT);
  pinMode(5, INPUT);  
  pinMode(4, OUTPUT);
  digitalWrite(4, HIGH);              //Включаем заряд конденсатора
  startTime = millis();               //Засекаем время
  while(analogRead(A2) < 648){}       //Ждем пока конденсатор не зарядится до 63,2% или 1,58 от  полной зарядки
  elapsedTime= millis() - startTime;  //Фиксируем время заряда
  //if (elapsedTime<2)elapsedTime=0;    // Борьба с шумами
  microFarads = ((float)elapsedTime / resistorValue) * 1000;  
 rez=microFarads;
 if (elapsedTime<=1)rez=0; 
  digitalWrite(4, LOW);               //Снимаем напряжение           
  pinMode(2, OUTPUT);                 //Разряжаем кондюк         
  digitalWrite(2, LOW);               //Закорачивая его на землю
  
  Serial.println(rez);
  delay(100);
  while(analogRead(A2) > 0){}         // Пока не разрядится         
  pinMode(2, INPUT);                  // Отключаем разряд 
} 

 

 
И пара фото:
Вход в режим измерения
 
И измерение конденсатора 10 мкФ
 
dimax
dimax аватар
Offline
Зарегистрирован: 25.12.2013

svm пишет:

Второй вариант позволяет измерять
емкости от 1 нФ, но требует схемных изменений (установки делителя для подачи опорного  напряжения на компаратор),

А внутренний ИОН не подходит? Типа как тут я делал.

 

svm
Offline
Зарегистрирован: 06.11.2016

dimax пишет:

svm пишет:

Второй вариант позволяет измерять
емкости от 1 нФ, но требует схемных изменений (установки делителя для подачи опорного  напряжения на компаратор),

А внутренний ИОН не подходит? Типа как тут я делал.

 

 Постоянная времени RC-цепи определяется как время, необходимое для того, чтобы напряжение на конденсаторе достигло 63,2% от его напряжения при полной зарядке.  Емкость в RC-цепочке связана с постоянной времени по уравнению: Tc = R* C (произведение сопротивления на емкость). Соответственно, емкость определится как: C = Tc/R. Заряд идет нелинейно. Поэтому подавать 1,1 В несколько некорректно, грубо нужно около 3,1 В. Конечно для пробника может и сойдет. Можно попробовать, но скорее всего достоверного результата удастся получить только в узком диапазоне емкостей. Ну и еще один минус от использования опорного 1,1 В - это его независимость от напряжения питания (читаем зарядки), что даст дополнительную не контролируемую погрешность.  В данном случае, больше бы подошло 3,3 В, но его на про мини нет. Сегодня удалось отделить переднюю панель от корпуса, но оказалось, что клей, которым вклеивал разъем для программирования попал еще между корпусом и дисплеем.