ADC Switches Library C++

Um mehrere Taster mit einem Pin einzulesen, kann ein Analog zu Digital Pin verwendet werden. Das Implementieren der Software besteht aus zwei Teilen.
Als erstens können mit "Bestimmen der Widertsände ADCSW.ino" die Widerstände bestimmt werden. Es ist zu beachten ist, dass die Klasse mit den Werten (int)ADC Pin, (boolean)hold until release, (int)Anzahl Taster und (float)Wert R1 initisalsiert werden muss. (int)ADC Pin bestimmt an welchem Pin sich die Schalter befinden. (boolean)hold until release verhindert das mehrfach einlesen bei längerem gedrückt halten des Tasters. (int)Anzahl Taster legt die Anzahl Taster fest. (float)Wert R1 legt den Wert des Widerstandes R1 fest. Mit xxx.ADCSW_res_calc(); können die restlichen Widerstände bestimmt werden. Die Software berechnet die Referenzwerte für die Widerstände R2 - RN. Leider sind nicht immer alle Widerstände präzise verfügbar. Deswegen kann der Anwender die einzusetzenden Widerstände, mit dem Serial Terminal manuell anpassen. Das Serial Terminal gibt zusätzlich das Widerstandsarray aus, welches für den nächsten Schritt gebraucht wird.
Als zweites können wie in "Laufzeit ADCSW.ino" beschrieben Taster ausgelesen werden. Um die berechneten Werte zu laden wird folgende Syntax im Setup verwendet:

float adcsw_res_values[] = {3300.00,6800.00,22000.00};

sws.ADCSW_res_manual(adcsw_res_values);

Damit das adcsw_res_values[] Array die richtigen Werte enthält, kann es direkt aus dem Serial Terminal (erster Schritt) kopiert werden. Mit sws.ADCSW_read_buttons(); kann ermittelt werden welcher Taster das gedrückt wird. Ist der Return Wert 0 so ist kein Taster gedrückt.

Um den dynamischen Speicher des Mikrokontrollers zu schonen, kann der Wert der maximal eingesetzten Schalter "#define ADCSW_max_keys 42" herabgesetzt werden. Das Minimum beträgt, die Anzahl eingesetzter Taster.

!!! Anwender die Mikrokontroller verwenden, deren ADC-Resolution nicht 10bit () betragen, müssen "#define ADCSW_ADC_resolution 1024" entsprechend ändern. !!!

 

Download Debouncer Library


Source Code

Bestimmen der Widertsände ADCSW.ino

#include "ADCSW.h"

ADCSW sws(A0, true, 4, 10000);

void setup() {
  Serial.begin(9600);
  while (!Serial) {;}
  Serial.println();

  sws.ADCSW_res_calc();
}

void loop()
{ }

Laufzeit ADCSW.ino

#include "ADCSW.h"

ADCSW sws(A0, true, 4, 10000);

void setup() {
  Serial.begin(9600);
  while (!Serial) {;}
  Serial.println();

  float adcsw_res_values[] = {3300.00,6800.00,22000.00};
  sws.ADCSW_res_manual(adcsw_res_values);
}

void loop()
{
  int b = sws.ADCSW_read_buttons();
  Serial.print("Button = ");
  Serial.println(b);
}

ADCSW.h

/*  ADCSW.cpp - Reads switches at an ADC Pin.  Created by Simon Aeschbacher, November 3 2015.  Released into the public domain.*/

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

#define ADCSW_max_keys 42
#define ADCSW_ADC_resolution 1024
#define ADCSW_ADC_max (ADCSW_ADC_resolution - 1)
#define ADCSW_tresh_max ((ADCSW_ADC_resolution/ADCSW_max_keys)-2)
#define ADCSW_tresh (ADCSW_tresh_max/2)

class ADCSW
{
  public:
    ADCSW(int adc_pin, boolean hur, int swnum, float resup);
	void ADCSW_res_calc(void);
	void ADCSW_res_manual(float* p_res_val);
	
	byte ADCSW_read_buttons(void);
	
	void ADCSW_print_res_val(void);
	void ADCSW_print_adc_val(void);
	
	void ADCSW_set_adc_pin(int adc_pin);
	int ADCSW_get_adc_pin(void);
	void ADCSW_set_hur(boolean hur);
	boolean ADCSW_get_hur(void);
	void ADCSW_set_swnum(byte swnum);
	byte ADCSW_get_swnum(void);
	void ADCSW_set_resup(float resup);
	float ADCSW_get_resup(void);

  private:
	void ADCSW_calc_adcval(void);
	byte ADCSW_adc_button(void);
  
	int 	_adc_pin;
	boolean _hur;
	byte 	_swnum;
	float 	_resup;
	byte	_bbu;
	
	int _ad_sw_val[ADCSW_max_keys];
	float _res_val[ADCSW_max_keys];

};

ADCSW.cpp

/*  ADCSW.cpp - Reads switches at an ADC Pin.  Created by Simon Aeschbacher, November 3 2015.  Released into the public domain.*/

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

#include "ADCSW.h"

ADCSW::ADCSW(int adc_pin, boolean hur, int swnum, float resup)
{
	_adc_pin = adc_pin;
	_hur = hur;
	_swnum = swnum;
	_resup = resup;
	
	pinMode(_adc_pin, INPUT);
	digitalWrite(_adc_pin, LOW);
}

void ADCSW::ADCSW_res_calc(void)
{
	RECALIBRATE:
	for (int i = 0; i < _swnum; i++) _ad_sw_val[i] = i * (ADCSW_ADC_max / _swnum);
	for (int i = 0; i < _swnum; i++) _res_val[i] = ((-1*(float)_ad_sw_val[i]*_resup)/((float)_ad_sw_val[i]-ADCSW_ADC_max));

	for (int i = 1; i < _swnum; i++)
	{
		int j = i;
		while(j>0)
		{
			_res_val[i] -= _res_val[j-1];
			j--;
		}
	}

	Serial.print("Resistor value R1 = ");
	Serial.print(_resup);
	Serial.println(" Ohm.");
	
	for (int i = 1; i < _swnum; i++)
	{
		Serial.print("Resistor value R");
		Serial.print(i+1);
		Serial.print(" ~");
		Serial.print(_res_val[i]);
		Serial.print(" Ohm. Set precise value R");
		Serial.print(i+1);
		Serial.print(" = ");		
		while (Serial.available() == 0);
		_res_val[i] = Serial.parseFloat();
		Serial.print(_res_val[i]);
		Serial.println(" Ohm.");
	}
	
	int tresh = ADCSW_ADC_max;
	for (int i = 1; i < _swnum; i++) if(_ad_sw_val[i] - _ad_sw_val[i-1] < tresh) tresh = _ad_sw_val[i] - _ad_sw_val[i-1];
	
	if (tresh < ADCSW_tresh_max)
	{
		Serial.println("*** ERROR Resistor values too imprecise ***");
		goto RECALIBRATE;
	}
	
	Serial.print("float adcsw_res_values[] = {");
	for (int i = 1; i < _swnum; i++)
	{
		Serial.print(_res_val[i]);
		if(i < _swnum-1) Serial.print(",");
	}
	Serial.println("};");
}

void ADCSW::ADCSW_res_manual(float *p_res_val)
{
	for (int i = 1; i < _swnum; i++) _res_val[i] = *(p_res_val + i - 1);
		
	ADCSW_calc_adcval();
		
	int tresh = ADCSW_ADC_max;
	for (int i = 1; i < _swnum; i++) if(_ad_sw_val[i] - _ad_sw_val[i-1] < tresh) tresh = _ad_sw_val[i] - _ad_sw_val[i-1];	
	if (tresh < ADCSW_tresh_max) Serial.println("*** ERROR Resistor values too imprecise ***");
}

byte ADCSW::ADCSW_adc_button(void)
{
	int adc_val = analogRead(_adc_pin);

	byte button = 0;
	
	for (int i = 0; i < _swnum; i++)
	{
		if( adc_val != ADCSW_ADC_max && adc_val > _ad_sw_val[i] - ADCSW_tresh && adc_val < _ad_sw_val[i] + ADCSW_tresh )
		{
			button = i+1;
			i = _swnum;
		}
	}
	return button;
}

byte ADCSW::ADCSW_read_buttons(void)
{
	byte button = ADCSW_adc_button();
	if(_hur)
	{
		delay(60);
		if (_bbu > 0 && button == 0) _bbu = 0;
		if(_bbu == button || button == 0) return 0;
		else _bbu = button;
	}
	return button;
}

void ADCSW::ADCSW_print_res_val(void)
{
	Serial.print("Resistor value R1 = ");
	Serial.print(_resup);
	Serial.println(" Ohm.");
	
	for (int i = 1; i < _swnum; i++)
	{
		Serial.print("Resistor value R");
		Serial.print(i+1);
		Serial.print(" = ");
		Serial.print(_res_val[i]);
		Serial.println(" Ohm.");
	}
}

void ADCSW::ADCSW_print_adc_val(void)
{
	for (int i = 0; i < _swnum; i++) Serial.println(_ad_sw_val[i]);
}

void ADCSW::ADCSW_calc_adcval(void)
{
	for (int i = 1; i < _swnum; i++)
	{
		float res_val = 0;
		int j = 0;
		while(j<=i)
		{
			res_val += _res_val[j];
			j++;
		}
		_ad_sw_val[i] = ADCSW_ADC_max * (res_val/(_resup + res_val));
	}
}

void ADCSW::ADCSW_set_adc_pin(int adc_pin)
{
	_adc_pin = adc_pin;
}
int ADCSW::ADCSW_get_adc_pin(void)
{
	return _adc_pin;
}

void ADCSW::ADCSW_set_hur(boolean hur)
{
	_hur = hur;
}
boolean ADCSW::ADCSW_get_hur(void)
{
	return _hur;
}

void ADCSW::ADCSW_set_swnum(byte swnum)
{
	_swnum = swnum;
}
byte ADCSW::ADCSW_get_swnum(void)
{
	return _swnum;
}

void ADCSW::ADCSW_set_resup(float resup)
{
	_resup = resup;
}
float ADCSW::ADCSW_get_resup(void)
{
	return _resup;
}