Project in progress
V2 View direct Resistors values in accodance tthe color code

V2 View direct Resistors values in accodance tthe color code © GPL3+

Shows to visually impaired or ignoring the resistors colour code, lazy techs etc..., either the exact value or value in E12 or E24 series

  • 1,569 views
  • 2 comments
  • 8 respects

Components and supplies

Apps and online services

About this project

I'm searching for a way to quickly display resistors values but without using a multimeter because this isn't really practical even if precise. For a few years now, resistors are harder to read due, mainly to my grand age but to the confusion between some colors as well, and the size of the rings which is more and more small. I wanted a real value easy to read, not 47200 but 47ko and a fast way to measure.

I tried several systems, even external 12 or 16bits converters, without obtaining what I wished, until I saw this project from Federico Vivaldi. https://create.arduino.cc/projecthub/federico-vivaldi

He cleverly uses the third state of ouput pins which implies no interfering impedance falsing the measure.

The principle is quite simple, a resistor, used as reference, is switched by the software from 1Mo to 100ohm in 5 steps. I change the values from 4.7Mo to 36ohm in 4 steps. A 36ohm resistor implies a current higher than allowed by the board manufacturer for an output pin, so I had to find a solution to this issue. The solution is quite simple, I put 5 outputs on 180ohm resistors and switch them all together, so the individual output pin current is lower than 30mA.

Actually, a servomotor drives a kind of flap which maintain the resistor under measure, (sorry english isn't my usual language). A button controls it, open or closed.

Another button switches the display between real value, E12 or E24 value.

Maybe a single button can do the two actions, a short push to change range, a long one to open or close the trap.

Of course, this device doesn't deserve a Nobel price but it can be usefull.

The schematic is up to date and won't be changed, I guess. The software isn't totally finished but I choose to publish anyway, I'll post all along the week-end until done. Thx for reading..

Code

ohm_meter.inoArduino
/*********************************************************************************************************************
    A direct reading ohm meter, values extracted from the 24 resistors serie

    Raphal Ollier (France)
    V1.1 - Software upgrades
    V1.2 - Add servo to lock resistor during measure, and switch to control it
    V1.3 - Switch and servo implemented
    v1.4 - Misc. Soft. Improvements
    v1.5 - Timed closing and end contact implemented 

    Largely inspired (and partly copied) from the work of Federico Vivaldi : Sorting resistors the lazy way
    https://create.arduino.cc/projecthub/federico-vivaldi/sorting-resistors-the-lazy-way-ceb557?ref=platform&ref_id=424_trending___&offset=7


 *********************************************************************************************************************/

// External libraries
#include <Servo.h>
#include <SPI.h>
#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
#define SCREEN_WIDTH 128 // OLED display width, in pixels
#define SCREEN_HEIGHT 32 // OLED display height, in pixels

// Constantes
#define BatDispWidth    20             // Display battery width
#define BatDispHeight   7              // Display battery height
#define BatDispPosX     105            // Display battery position
#define BatDispPosY     0

#define ServoCmd        9           // Data output for PWM
#define SwitchInput     8           // Data input for switch
#define ServoEnd        10          // Data input for end contact


// Declaration for an SSD1306 display connected to I2C (SDA, SCL pins)
#define OLED_RESET     4 // Reset pin # (or -1 if sharing Arduino reset pin)
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);

#define ServoOpen       120         // 180 max. quasiment 1 par unit         
#define ServoClosed     0
int ServoVal = ServoOpen / 2;         // variable for servo pos
int SwCount = 3;         // counter init for switch debounce
int VCount = SwCount;    // counter variable for switch debounce
int ActiveKey = 1;       // variable key active
boolean Opened = true;   // variable for door state

// Srie de rsistances par 24
int SerieVal[] =        {10, 11, 12, 13, 15, 16, 18, 20, 22, 24, 27, 30,
                         33, 36, 39, 43, 47, 51, 56, 62, 68, 75, 82, 91, 100
                        };



int DelayConv = 10;    // time allocated to A/D conversion
int MeasuresNbr = 10;   // number of conversions and divider

int MinRaw = 300;       // original value 350
int MaxRaw = 820;       // original value 800

int R1 = 100;           // Base resistors
int R2 = 1000;
int R3 = 10000;
long R4 = 100000;
long R5 = 1000000;
long Rn;                // Base resistor used for conversion

int D2 = 2;             // Data Bus
int D3 = 3;
int D4 = 4;
int D5 = 5;
int D6 = 6;

int ValBrut = 0;

int StrLength = 0;      //chain length

String ValueStr = "000" ;
String SuffixStr = " Mo";

float Raw = 0;          // Raw read value
float Ru = 0;           // Unknown resistor value

int AnalogRead = A0;    // Analog port for reading
Servo Trappe;
void setup() {
  // ******************  Adafruit address test routine **************************
  Serial.begin(9600);
  // Serial.println (display.begin(SSD1306_SWITCHCAPVCC, 0x3C));

  // SSD1306_SWITCHCAPVCC = generate display voltage from 3.3V internally
  if (!display.begin(SSD1306_SWITCHCAPVCC, 0x3C)) { // Address 0x3C for 128x32
    Serial.println(F("SSD1306 allocation failed"));
    for (;;); // Don't proceed, loop forever
  }
  // ****************** Draw rectangles at the beginning of the program *********
  Rectangles();
  Trappe.attach(ServoCmd);
  GoOpen();
  delay(1000);                       // Time for servo to arrive
  pinMode(SwitchInput, INPUT);
  pinMode(ServoEnd, INPUT);
}

// ****************** Main loop ***********************************************
void loop() {
  ActiveKey = digitalRead(SwitchInput);
  if (ActiveKey == 0) {             // key on
    if (VCount == 1) {
      if (Opened == true) {   // test if opened
        GoClose();
        VCount--;
      }      else {
        GoOpen();
        VCount--;
      }
    } else {            // VCount<>1
      if (VCount != 0) {            // VCount<>0
        VCount--;
      }
    }
  } else {
    VCount = SwCount;               // reinit counter
  }

  pinMode(D2, OUTPUT);              // original setup, REF 1M
  pinMode(D3, INPUT);
  pinMode(D4, INPUT);
  pinMode(D5, INPUT);
  pinMode(D6, INPUT);

  digitalWrite(D2, HIGH);
  Reading_analog_in();
  Rn = R5;

  if (Raw < MinRaw || Raw > MaxRaw) {           // REF 100k
    digitalWrite(D2, LOW);
    pinMode(D2, INPUT);
    pinMode(D3, OUTPUT);
    digitalWrite(D3, HIGH);
    Reading_analog_in();
    Rn = R4;

    if (Raw < MinRaw || Raw > MaxRaw) {         // REF 10k
      digitalWrite(D3, LOW);
      pinMode(D3, INPUT);
      pinMode(D4, OUTPUT);
      digitalWrite(D4, HIGH);
      Reading_analog_in();
      Rn = R3;

      if (Raw < MinRaw || Raw > MaxRaw) {       // REF 1k
        digitalWrite(D4, LOW);
        pinMode(D4, INPUT);
        pinMode(D5, OUTPUT);
        digitalWrite(D5, HIGH);
        Reading_analog_in();
        Rn = R2;

        if (Raw < MinRaw || Raw > MaxRaw) {     // REF 100 impossible to decrease
          digitalWrite(D5, LOW);
          pinMode(D5, INPUT);
          pinMode(D6, OUTPUT);
          digitalWrite(D6, HIGH);
          Reading_analog_in();
          Rn = R1;
        }
      }
    }
  }
  if (Raw > 1020) {     // Raw value out of window
    Ru = 11000000;      // to display ">10 Mo"
  } else {
    Ru = ((Raw * Rn) / (1024 - Raw)); // Calculation for resistor to find but lower than 10Mo
  }

  // ****************** Display assignments & calculation ***********************

  // NEEDS IMPROVEMENTS !!

  StrLength = String(Ru, 0).length();

  if (StrLength > 7) {
    ValueStr = ">10";
    SuffixStr = " Mo";
  } else {
    if (StrLength > 6) {
      /*    ValueStr = "<10";             // not used, only to debug
          SuffixStr = " Mo";*/
      Ru = Ru / 100000;
      Plusproche();               // call to comparison routine

      ValueStr = String(SerieVal[ValBrut] / 10);
      SuffixStr = " Mo";
      if (ValBrut == 24 ) {
        ValueStr = ("10");
        SuffixStr = " Mo";
      }
    }  else {
      if (StrLength > 5) {
        Ru = Ru / 10000;
        Plusproche();               // call to comparison routine
        ValueStr = String(SerieVal[ValBrut]);
        SuffixStr = "0 ko";
        if (ValBrut == 24) {
          ValueStr = ("1");
          SuffixStr = " Mo";
        }
      } else {
        if (StrLength > 4) {
          Ru = Ru / 1000;
          Plusproche();             // call to comparison routine
          ValueStr = String(SerieVal[ValBrut]);
          SuffixStr = " ko";
        } else {
          if (StrLength > 3) {
            Ru = Ru / 100;
            Plusproche();           // call to comparison routine
            ValueStr = String(SerieVal[ValBrut]).substring(0, 1) + "." + String(SerieVal[ValBrut]).substring(1, 2);
            SuffixStr = " ko";
          } else {
            if (StrLength > 2) {
              Ru = (Ru / 10);
              Plusproche();         // call to comparison routine
              ValueStr = String(SerieVal[ValBrut]);
              SuffixStr = "0 ohm";
              if (ValBrut == 24) {
                ValueStr = ("1");
                SuffixStr = " ko";
              }
            } else {
              Plusproche();         // call to comparison routine
              ValueStr = String(SerieVal[ValBrut]);
              if (ValBrut == -1) {
                ValueStr = ("< 10");
              }
              SuffixStr = " ohm";
            }
          }
        }
      }
    }
  }
  DisplayOled();                    // call display routine
  // impression();                  // call to debug infos
}

void Plusproche() {
  for (int i = 0; i < 25; i++) {    // scan into the 24 normalized values
    int SerieDifference = (Ru - SerieVal[i]);   // dif between R and normalized
    if (SerieDifference == 0) {                 // exact norm value
      ValBrut = i;
      break;
    }
    if (SerieDifference < 0) {                  // next norm value
      int old = (Ru - SerieVal[i - 1]);
      if (old - abs( SerieDifference) < 0) {    // test n with n-1
        ValBrut = (i - 1);
      } else {
        ValBrut = (i);
      }
      break;
    }
  }
}

void GoClose() {
  ServoVal = (ServoOpen / 2);      // semi fermeture de la trappe
  while (digitalRead(ServoEnd) && (ServoVal > ServoClosed)) {
    ServoVal--;
    Trappe.write (ServoVal);
    Serial.println(ServoVal);
    delay(10);
  }
  Trappe.write (ServoVal-5);
  Serial.println(ServoVal);
  Opened = false;
}
void GoOpen() {
  Trappe.write (ServoOpen);         // ouverture de la trappe
  Opened = true;
}
void Reading_analog_in () {
  delay(DelayConv);                             // delay for conversion
  Raw = 0;                                      // init Raw ValueStr
  for (int x = 0; x < MeasuresNbr; x++) {
    Raw += analogRead(AnalogRead);
  }
  Raw = Raw / MeasuresNbr;                      // average value
}

void DisplayOled() {
  display.clearDisplay();
  display.setTextSize(1);
  display.setTextColor(WHITE);
  display.setCursor(0, 0);
  display.print("S24");

  // *************** display battery status **************
  display.setCursor(60, 0);
  display.print("Battery ");
  display.drawRect(BatDispPosX, BatDispPosY, BatDispWidth, BatDispHeight, WHITE);
  display.fillRect(BatDispPosX, BatDispPosY, BatDispWidth * 0.5, BatDispHeight, WHITE); // battery at 50%

  // *************** display resistor value **************
  display.setCursor(0, 12);
  display.setTextSize(3);
  display.print(ValueStr);
  display.print(SuffixStr);
  display.display();                // needed to reinit drawings
}

void Rectangles() {                 // routine which draws in and out rectangles, purely cosmetic !
  display.clearDisplay();
  for (int i = 0; i < 16; i++) {
    display.drawRect(i, i, (SCREEN_WIDTH - 1) - 2 * i, (SCREEN_HEIGHT - 1) - 2 * i, WHITE);
    display.display();
    delay(100);
    display.drawRect(i, i, (SCREEN_WIDTH - 1) - 2 * i, (SCREEN_HEIGHT - 1) - 2 * i, BLACK);
  }
  for (int i = 15; i > 0; i--) {
    display.drawRect(i, i, (SCREEN_WIDTH - 1) - 2 * i, (SCREEN_HEIGHT - 1) - 2 * i, WHITE);
    display.display();
    delay(100);
    display.drawRect(i, i, (SCREEN_WIDTH - 1) - 2 * i, (SCREEN_HEIGHT - 1) - 2 * i, BLACK);
  }
}

void impression() {                 // routine to print debug values, not necessary
  Serial.print("Raw : ");
  Serial.println(Raw);
  Serial.print("Rn : ");
  Serial.println(Rn);
  Serial.print("ValBrut : ");
  Serial.println(ValBrut);
  Serial.print("Ru aprs = ");
  Serial.println(Ru);
  Serial.print ("Valeur et Suffixe : ");
  Serial.print(ValueStr);
  Serial.println(SuffixStr);
  Serial.println (StrLength);
  Serial.println (" ");
}

Schematics

PDF schematic

Comments

Similar projects you might like

Sorting Resistors the Lazy Way

Project tutorial by Federico Vivaldi

  • 11,296 views
  • 39 comments
  • 78 respects

Soldering Iron Controller for Hakko 907 v.2

Project tutorial by Alexander

  • 30,614 views
  • 178 comments
  • 71 respects

Tinkerer Meter, a Bluetooth Multimeter Made with Arduino

Project tutorial by Federico Vivaldi

  • 1,939 views
  • 0 comments
  • 10 respects

I2C OLED Display Using Arduino/NodeMCU

by Tarantula3

  • 16,374 views
  • 3 comments
  • 36 respects

7-Segment Clock with Arduino Nano + DS3231 + LDR

Project tutorial by Ingo Lohs

  • 11,582 views
  • 21 comments
  • 32 respects

Interfacing Nokia 5110 LCD with Arduino

by Muhammad Aqib

  • 7,638 views
  • 3 comments
  • 8 respects
Add projectSign up / Login