LusoRobótica - Robótica em Português
Robótica => Tutoriais => Tópico iniciado por: DanBar em 26 de Fevereiro de 2009, 10:29
-
Como fazer um sensor de voltagem analógico com 2 resistencia baseado pela formula divisão voltagem.
Formula: Vout = Vin / (R1 + R2) * R2
(https://lusorobotica.com/proxy.php?request=http%3A%2F%2Fupload.wikimedia.org%2Fwikipedia%2Fen%2Fd%2Fdb%2FResistive_divider.png&hash=fb337af617cec9ab4d98ae427a806520f0466551)
A Voltagem de referencia que utilizei foi um transformador de portatil que debita 18.84 Volts.
Material utilizado para fazer o circuito:
1 resistencia variável de 10k
1 resistencia 10k
O Valor máximo de entrada para uma porta analógica do Arduino tem que ser de 5 volts. Ou melhor 5.20Volts para uma referencia de 1023 (importante para o mapeamento)
Depois de ligar tudo conforme a imagem acima:
(https://lusorobotica.com/proxy.php?request=http%3A%2F%2Fwww.2mhi.com%2Ficar%2Farduino%2Fvolt1.jpg&hash=ec140aeb9a11a70b212e5a34f13a74613048c172)
(https://lusorobotica.com/proxy.php?request=http%3A%2F%2Fwww.2mhi.com%2Ficar%2Farduino%2Fvolt2.jpg&hash=af08cee4e62614a371fdbc5c4c1788dd7c9e6928)
(https://lusorobotica.com/proxy.php?request=http%3A%2F%2Fwww.2mhi.com%2Ficar%2Farduino%2Fvolt3.jpg&hash=a02f7dac67684b1d4aec5aac857380c1b0e14ac3)
Regular a resistencia variável para que a voltagem de saida seja exatamente 5.20volts (com ajuda do multimetro). Só depois podem ligar á porta analógica do arduino.
Depois correr o código e experimentar uma voltagem menor na entrada (exemplo outro transformador 12volts ou 9 volts)
Poderam ver o arduino informar a voltagem que está a entrar na porta analógica.
Com a resistencia variável de 10K poderá entrar até 30Volts.
Atenção que o Ground do arduino tem que ser ligado ao ground do transformador, pois tem que ser o mesmo.
Fica aqui o código para experimentarem.
/*
Volts Monitor Sensor
/ 10k Variável
+ ----/\/\/\--------|
/ |-----> Analog In
10k |
- ------/\/\/\------|
|
---------------------- Grd
By Daniel Barradas (iCAR)
*/
float RefVolts = 18.84; // Voltagem Entrada Referencia
int AnalogPort = 0; // Porta Analógica
void setup() {
Serial.begin(9600); // Comunica com o PC
}
void loop() {
Serial.print(GetVolts(AnalogPort,RefVolts)); Serial.println(" v");
//Serial.print(AnalogVoltIn(AnalogPort)); Serial.println(" v"); // Debug
//Serial.println(analogRead(AnalogPort)); // Debug
delay(100);
}
/*
Lê a Voltage de entrada na porta analógica com máximo de 5.20 para 1023
By Daniel Barradas (iCAR)
*/
float AnalogVoltIn(int AnalogPin) {
float AnalogRead;
AnalogRead = analogRead(AnalogPin);
return MapFl(AnalogRead, 0, 1023, 0, 5.20);
}
/*
Lê a Voltage de entrada na porta analógica com máximo de voltagem referenciada (18.84)
By Daniel Barradas (iCAR)
*/
float GetVolts(int AnalogPin, float MaxVols) {
float AnalogRead;
AnalogRead = analogRead(AnalogPin);
return MapFl(AnalogRead, 0, 1023, 0, MaxVols);
}
/*
MapFl Substitui a Funcção Map, pois retorna Float
By Daniel Barradas (iCAR)
*/
float MapFl(float value, float istart, float istop, float ostart, float ostop) {
return ostart + (ostop - ostart) * ((value - istart) / (istop - istart));
}
Cumprimentos
-
Há é verdade muito importante. como as variáveis são "floats", o código tem que ser compilado com a ultima versão do IDE 0013.
Pois o Serial.Println já funciona com floats. ;)
-
Fica aqui a placa PCB.
(https://lusorobotica.com/proxy.php?request=http%3A%2F%2Fwww.2mhi.com%2Ficar%2Farduino%2FVolt_Sensor_pcb.jpg&hash=65974ca173b84a888b6ee8d0e1cc876beecfabd3)
Melhor resolução:
http://www.2mhi.com/icar/arduino/Volt_Sensor_pcb.bmp (http://www.2mhi.com/icar/arduino/Volt_Sensor_pcb.bmp)
-
Se quieres analizar melhor podem verificar este site, onde podem calcular as resistencias necessárias para cada voltagem.
http://ourworld.compuserve.com/homepages/Bill_Bowden/r2.htm (http://ourworld.compuserve.com/homepages/Bill_Bowden/r2.htm)
Como podem verificar este esquema gasta muito pouco 0.005A
(https://lusorobotica.com/proxy.php?request=http%3A%2F%2Fwww.2mhi.com%2Ficar%2Farduino%2FVoltage%2520Divider.jpg&hash=8c4dd72bbbb10313b55833293271cebcf4c37a8d)
-
Muito bom tutorial :)
Um bocadinho Off-topic: Um divisor de tensão também muito usado quando temos sensores que são resistências variáveis, se colocar-mos um sensor no lugar de uma daquelas resistências e a Vin=5V o Vout vai variar consoante o valor da resistência do sensor varia!
-
Certo.
Está offtopic porque pensava que não tinha direito de postar nos tutotials, mas afinal é nas noticias. Dhaaa.
Modereadores / admin se quiseres podem muda-lo para Tutorial. Obrigado.
-
já está iCAR ;)
bom tutorial :)
-
Esquema que utilizo:
10k
12Volts >----------------/\/\/\------- |
( + ) 10k
| |
grd----| | ----------> 5Volts------> ligar ao pino 0 Analogico
Ligas um voltimetro á saída da resistencia variável / potenciometro e regulas até o voltimetro acusar 5 Volts.
Depois uso este código no arduino para ler a voltagem:
int VoltVal = 0;
int VoltValPerc = 0;
char value2[4] ;
void setup() {
Serial.begin(9600);
}
void loop() {
getVoltage(0);
delay(5);
Serial.print("Volts: ");
Serial.print(VoltVal); // debug value
Serial.print(" ");
Serial.print(VoltValPerc);
Serial.println("%");
}
void getVoltage(int voltPin){
int val = 0;
VoltVal = 0;
val = analogRead(voltPin); // read the input pin
VoltVal = map(val, 0, 1023, 0, 12); // valor em volts
VoltValPerc = map(val, 0, 1023, 0, 100); // valor em percentagem
}
-
Estou a usar este codigo para um projecto do LCD se possivel poderiam ajudar-me a resolver algumas duvidas do codigo?
O segundo codigo parece mais clean e facil de entender, e para o que eu quero até funciona bem mas falta-lhe 2 casas decimais, o codigo como está apenas mostra valores de 0v a 12v eu desejava que mostra-se 0.00v a 12.00v.
O primeiro codigo faz o que eu quero mas... não precebo nada da ultima parte!! mapeamentos e re-mapiamentos :) mas este codigo apesar de ter as casa decimais, o inicio do valor é da esquerda para a direita o que me deixa um caracter no LCD quando baixo do 10.00 para os 9.00.
Ex:
10.00
9.990 (o ultimo 0 ficou la do valor de 10.00)
Existe maneira de colocar os valores de 00.00v a 12.00v, era uma maneira facil de resolver esta situação.
-
Boas.
Tens que limpar sempre no lcd antes de ler o valor que pretendes, ou então verificas o tamanho da string que vais enviar para o lcd e acrescentas um zero á esquerda quando a string é inferior a 5 caracteres (00.00)
Ex:
#include <string.h>
#include <stdlib.h>
#include <floatToString.h>
#include <LCD3Wire.h>
#define BatPin 3 // Volts Sensor
float VoltRef = 12.0; // Voltagem de referencia de alimentacao
float BatVolt = 0.00; // Guarda o valor com 2 casa decimais da bateria
byte BatPerc = 0; // Guarda a percentagem da bateria
char BatVoltTxt[6]; // Guarda o valor da bateria para serial.print ou lcd
// **********************************************************
//
// Funcao: getBatVal - Ler carga da bateria
// Retorno: Nada - grava o valor na variavel BatVol e BatPerc
//
// **********************************************************
static void getBatVal(void){
int val = 0;
val = analogRead(BatPin); // read the input pin
BatVolt = mapFloat(val, 0, 1023, 0.0, VoltRef); // valor em volts
BatPerc = map(val, 0, 1023, 0, 100); // valor em percentagem
floatToString(BatVoltTxt, BatVolt, 2);
Serial.print("Bat:");Serial.print(BatPerc,DEC);Serial.print("% ");Serial.print(BatVoltTxt);Serial.println("V");
}
}
static void LcdVolPrint(int Col){
if (strlen(BatVoltTxt)<5){
lcd.cursorTo(1, Col);
lcd.printIn("0");
lcd.cursorTo(2, Col+1);
lcd.printIn(BatVoltTxt);
} else {
lcd.cursorTo(2, Col);
lcd.printIn(BatVoltTxt);
}
}
Espero que ajude.
Nota: Atenção que eu estou a utilizar a livraria 3 wire para lcd (#include <LCD3Wire.h>)
se utilizares outras esses comandos de escrita do lcd não devem funcionar.
-
Estou a ter alguns problemas com o floaToString... dá-me este erro ao copilar
/floatToString.h: In function 'char* floatToString(char*, float, int, int, bool)':
/floatToString.h:73: error: 'itoa' was not declared in this scope
/floatToString.h:89: error: 'itoa' was not declared in this scope
Tou farto de inventar mas não consigo meter a funcionar, tenho a floaToString na root do projecto e só estou a usar o serial para ler os dados na consola, removi toda a parte do LCD e o #include <floatToString.h> passou a #include "floatToString.h"
Antes de não conseguir copilar dava este erro: In function 'void getBatVal()': error: 'MapFl' was not declared in this scop
Acho que faltava isto ao codigo:
float MapFl(float value, float istart, float istop, float ostart, float ostop) { return ostart + (ostop - ostart) * ((value - istart) / (istop - istart));}
Desculpa mas ando aqui aos papeis :) começei numa coisa simples e já me estou a enterrar lol
-
Ops. Este código é antigo para mim. Sory
// *******************************************************************
//
// Funcao:MapFloat - Mapear valores em float
// Retorno: valor float
//
// *****************************************************************
float mapFloat(float value, float istart, float istop, float ostart, float ostop) {
return ostart + (ostop - ostart) * ((value - istart) / (istop - istart));
}
-
Tens que criar o ficheiro floatToString.h na directoria arduino-00xx\libraries\floatToString
// floatToString.h
//
// Tim Hirzel
// tim@growdown.com
// March 2008
// float to string
//
// If you don't save this as a .h, you will want to remove the default arguments
// uncomment this first line, and swap it for the next. I don't think keyword arguments compile in .pde files
#include <string.h>
#include <ctype.h>
#include <math.h>
#include <stdlib.h>
//char * floatToString(char * outstr, float value, int places, int minwidth=, bool rightjustify) {
char * floatToString(char * outstr, float value, int places, int minwidth=0, bool rightjustify=false) {
// this is used to write a float value to string, outstr. oustr is also the return value.
int digit;
float tens = 0.1;
int tenscount = 0;
int i;
float tempfloat = value;
int c = 0;
int charcount = 1;
int extra = 0;
// make sure we round properly. this could use pow from <math.h>, but doesn't seem worth the import
// if this rounding step isn't here, the value 54.321 prints as 54.3209
// calculate rounding term d: 0.5/pow(10,places)
float d = 0.5;
if (value < 0)
d *= -1.0;
// divide by ten for each decimal place
for (i = 0; i < places; i++)
d/= 10.0;
// this small addition, combined with truncation will round our values properly
tempfloat += d;
// first get value tens to be the large power of ten less than value
if (value < 0)
tempfloat *= -1.0;
while ((tens * 10.0) <= tempfloat) {
tens *= 10.0;
tenscount += 1;
}
if (tenscount > 0)
charcount += tenscount;
else
charcount += 1;
if (value < 0)
charcount += 1;
charcount += 1 + places;
minwidth += 1; // both count the null final character
if (minwidth > charcount){
extra = minwidth - charcount;
charcount = minwidth;
}
if (extra > 0 and rightjustify) {
for (int i = 0; i< extra; i++) {
outstr[c++] = ' ';
}
}
// write out the negative if needed
if (value < 0)
outstr[c++] = '-';
if (tenscount == 0)
outstr[c++] = '0';
for (i=0; i< tenscount; i++) {
digit = (int) (tempfloat/tens);
itoa(digit, &outstr[c++], 10);
tempfloat = tempfloat - ((float)digit * tens);
tens /= 10.0;
}
// if no places after decimal, stop now and return
// otherwise, write the point and continue on
if (places > 0)
outstr[c++] = '.';
// now write out each decimal place by shifting digits one by one into the ones place and writing the truncated value
for (i = 0; i < places; i++) {
tempfloat *= 10.0;
digit = (int) tempfloat;
itoa(digit, &outstr[c++], 10);
// once written, subtract off that digit
tempfloat = tempfloat - (float) digit;
}
if (extra > 0 and not rightjustify) {
for (int i = 0; i< extra; i++) {
outstr[c++] = ' ';
}
}
outstr[c++] = '\0';
return outstr;
}
/* EXAMPLE APPLICATION
#include "floatToString.h" //set to whatever is the location of floatToStrig
void setup() {
Serial.begin(9600);
char buffer[25]; // just give it plenty to write out any values you want to test
// ==========================================
// now run a series on the floatToString function
// looking at the precision of the float
Serial.println("floatToString(buffer, 1000000.321 , 5);");
Serial.println(floatToString(buffer, 1000000.321, 5));
Serial.println();
Serial.println("floatToString(buffer, 100000.321 , 5);");
Serial.println(floatToString(buffer, 100000.321, 5));
Serial.println();
Serial.println("floatToString(buffer, 10000.321 , 5);");
Serial.println(floatToString(buffer, 10000.321, 5));
Serial.println();
Serial.println("floatToString(buffer, 1000.321 , 5);");
Serial.println(floatToString(buffer, 1000.321, 5));
Serial.println();
Serial.println("floatToString(buffer, 100.321 , 5);");
Serial.println(floatToString(buffer, 100.321, 5));
Serial.println();
// ==========================================
// looking at effect of changing precision
Serial.println("floatToString(buffer, 100000.321 , 6);");
Serial.println(floatToString(buffer, 100000.321, 6));
Serial.println();
Serial.println("floatToString(buffer, 100000.321 , 7);");
Serial.println(floatToString(buffer, 100000.321, 7));
Serial.println();
Serial.println("floatToString(buffer, 100000.321 , 8);");
Serial.println(floatToString(buffer, 100000.321, 8));
Serial.println();
Serial.println("floatToString(buffer, 100000.321 , 9);");
Serial.println(floatToString(buffer, 100000.321, 9));
Serial.println();
// ==========================================
// check negatives and rounding, and some edge cases
Serial.println("floatToString(buffer, -5004.321 , 5);");
Serial.println(floatToString(buffer, -5004.321 , 5));
Serial.println();
Serial.println("floatToString(buffer, 99.999 , 3); ");
Serial.println(floatToString(buffer, 99.999 , 3));
Serial.println();
Serial.println("floatToString(buffer, 100, 1);");
Serial.println(floatToString(buffer, 100, 1));
Serial.println();
Serial.println("floatToString(buffer, -100.999 , 1);");
Serial.println(floatToString(buffer, -100.999 , 1));
Serial.println();
Serial.println("floatToString(buffer, -54.321 , 0);");
Serial.println(floatToString(buffer, -54.321 , 0));
Serial.println();
Serial.println("floatToString(buffer, 0.321 , 5);");
Serial.println(floatToString(buffer, 0.321 , 5));
Serial.println();
Serial.println("floatToString(buffer, -1.0001 , 5);");
Serial.println(floatToString(buffer, -1.0001 , 5));
Serial.println();
Serial.println("floatToString(buffer, -0.000001 , 5);");
Serial.println(floatToString(buffer, -0.000001 , 5));
Serial.println();
Serial.println("floatToString(buffer, 0.000001 , 5);");
Serial.println(floatToString(buffer, 0.000001 , 5));
Serial.println();
Serial.println("floatToString(buffer, -0.00001 , 5);");
Serial.println(floatToString(buffer, -0.00001 , 5));
Serial.println();
Serial.println("floatToString(buffer, 0.000099 , 5);");
Serial.println(floatToString(buffer, 0.000099 , 5));
Serial.println();
// alternative technique that depends on <stdio.h>
//Serial.println("Serial.println(dtostrf(-1.0001, 2, 5, s));");
//char s[32];
// Serial.println(dtostrf(-1.0001, 2, 5, s)));
delay(1000);
Serial.println();
}
void loop() {
}
*/
-
Respondo-te aqui para a comunidade ver:
O programa tem que ter sempre esta estrutura:
void setup(){
// aqui inicia a configuração
}
void loop(){
// aqui chamas as tuas funções
}
faz assim:
#include <string.h>
#include <stdlib.h>
#include <floatToString.h>
#include <LCD3Wire.h>
#define BatPin 3 // Volts Sensor
float VoltRef = 12.0; // Voltagem de referencia de alimentacao
float BatVolt = 0.00; // Guarda o valor com 2 casa decimais da bateria
byte BatPerc = 0; // Guarda a percentagem da bateria
char BatVoltTxt[6]; // Guarda o valor da bateria para serial.print ou lcd
// lcd 3 wire
#define Lcd_CLK_Pin 5 // Clock pin pwm
#define Lcd_DOUT_Pin 6 // Dout pin pwm
#define Lcd_STR_Pin 7 // Strobe pin
#define LCD_LINES 2 // number of lines in your display
//create object to control an LCD.
LCD3Wire lcd = LCD3Wire(LCD_LINES, Lcd_DOUT_Pin, Lcd_STR_Pin, Lcd_CLK_Pin);
void setup(){
Serial.begin(9600); // verifica se comunicas a 9600
lcd.clear(); // usa a tua função para limpar o lcd
}
void loop(){
getBatVal();
LcdVolPrint(1); // imprime no lcd coluna 1
}
// **********************************************************
//
// Funcao: getBatVal - Ler carga da bateria
// Retorno: Nada - grava o valor na variavel BatVol e BatPerc
//
// **********************************************************
static void getBatVal(void){
int val = 0;
val = analogRead(BatPin); // read the input pin
BatVolt = mapFloat(val, 0, 1023, 0.0, VoltRef); // valor em volts
BatPerc = map(val, 0, 1023, 0, 100); // valor em percentagem
floatToString(BatVoltTxt, BatVolt, 2);
Serial.print("Bat:");Serial.print(BatPerc,DEC);Serial.print("% ");Serial.print(BatVoltTxt);Serial.println("V");
}
static void LcdVolPrint(int Col){
if (strlen(BatVoltTxt)<5){
lcd.cursorTo(1, Col);
lcd.printIn("0");
lcd.cursorTo(2, Col+1);
lcd.printIn(BatVoltTxt);
} else {
lcd.cursorTo(2, Col);
lcd.printIn(BatVoltTxt);
}
}
// *******************************************************************
//
// Funcao:MapFloat - Mapear valores em float
// Retorno: valor float
//
// *****************************************************************
float mapFloat(float value, float istart, float istop, float ostart, float ostop) {
return ostart + (ostop - ostart) * ((value - istart) / (istop - istart));
}
Compilei no meu IDE18 e funcionou.
-
Pois tava a meter o static void fora do loop, agora funciona :D
-
boa noite.
tenho uma fonte de alimentaçao de 0 a 30 volts 0 a 5 amp e gostaria de lhe adicionar um voltimetro amperimetro com lcd 2x16, ja que o actual é analógico, estou interessado nesse tópico, e ver se consigo adaptar a minha fonte somente, não consegui ver o esquema, pois o link ja esta off, será possivel meterem o link de novo.
desde ja agradeço
-
Pois o esquema foi-se, alias todas as minhas imagens sumiram, pois a minha página teve um ataque e o ISP (fornecedor alojamento) faliu.
Se vires com atenção tenho o esquema desenhado com traços mais acima. ;)