ayuda con codigo para medir ac

hola les comento lo siguiente estoy usando este codigo el cual encontre en un post para medir tension y corriente ac pero al querer compilarlo me da los siguientes errores

sketch_jun25a.ino: In function ‘void tension()’:
sketch_jun25a.ino:59:7: error: invalid conversion from ‘int*’ to ‘int’ [-fpermissive]
sketch_jun25a.ino:61:7: error: invalid conversion from ‘int*’ to ‘int’ [-fpermissive]
sketch_jun25a.ino:63:7: error: invalid conversion from ‘int*’ to ‘int’ [-fpermissive]

el codigo es el siguiente

#include <LiquidCrystal.h> // Libreria para el display 

LiquidCrystal lcd (12, 11, 5, 4, 3, 2); 


int i=0; // Se inican los subindices para las matrices 
int j=0; 
int lecturasv[50]; // inicia dos matrices unidmensuinal con 50 posiciones cada una 
int lecturasi[50]; 
int valor1=0; 
int valor2=0; //se inician las variables de entrada valor 1 ,2 ,3 
int valor3=0; 
int pend1=0; // se inician las variables pend 1 y 2 
int pend2=0; 
float volt=0; // Se inician la varialbes para tension , corriente y potencia 
float corr=0; 
float pot=0; 


void setup() 
{ 
Serial.begin (9600); //inicia comunicacion serial 

lcd.begin(16, 2); // declara lcd de dos lineas 
lcd.print("Pot: "); // escribe la palabra Pot 

for(int cont=0;cont<50;cont++) //hace un bucle for 
{ 
lecturasv[cont]=analogRead(A0); // Se toman 50 lecturas con un intervalo de 1 milisegudo obteniendose asi el equivalente dos cicos y medio de valores 
// en los semiciclos negativos en ADC da valores nulos.- 
delay(1); 
} 

for(int cont=0;cont<50;cont++) //hace un bucle for 
{ 
lecturasi[cont]=analogRead(A5); // Se toman 50 lecturas con un intervalo de 1 milisegudo obteniendose asi el equivalente dos cicos y medio de valores 
// en los semiciclos negativos en ADC da valores nulos.- 
delay(1); 
} 

} 

void loop(){ 
tension(); 
corriente(); 
} 

//--------------------------------------------------------------------------------------------------------------------------------------------- 

void tension() 
{ 
if(i>47) // dependiendo de donde inicie la toma de lecturas pueden llegar a hacerse mas de 50 iteracioens sin llegar al resultado 
// de alli la pregunta de if>47 
{ 
i=0; // si es cierto debe reiniciar !! 
setup(); // reinicio 
} 

valor1=lecturasv; 
i++; 
valor2=lecturasv; // en loop se toman 3 lecturas consecutivas y se caculan dos pendientes consecutivas 
i++; 
valor3=lecturasv; 

pend1=valor2-valor1; // calcula pendiente 1 
pend2=valor3-valor2; // calcula pendiente 2 


if (pend1>0 && pend2<0&& i>3&& valor1>10) //cuando las mismas cambian de signo alli estamos en el maximo (ademas forzamos a que haya por lo menos tres iteraciones para mas exactitud) 
{ 
volt=20*(valor2*0.0332+0.7); // alli calculamos el valor eficaz como 5.1/1023*8.2/1/1.4142 = 0.0332 (1.1442 es raiz de 2 ) 



i=0; //se resetea i , se manda a setup nuevamente y se repite el ciclo 
corriente(); // manda a hacer rutina corriente 
} 
i--; // si sale por "no" se debe decrementar i una vez , ya que se incremento dos veces en la toma de los tres valores 
} 

//--------------------------------------------------------------------------------------------------------------- 

void corriente() 
{ 
if(j>47) // dependiendo de donde inicie la toma de lecturas pueden hacerse mas de 50 iteracioens sin llegar al resultado 
// de alli la pregunta de if>47 
{ 
j=0; // si es cierto debe reiniciar 
setup(); // reinicio 
} 

valor1=lecturasi[j]; 
j++; 
valor2=lecturasi[j]; // en loop se toman 3 lecturas consecutivas y se caculan dos pendientes consecutivas 
j++; 
valor3=lecturasi[j]; 

pend1=valor2-valor1; // calcula pendiente 1 
pend2=valor3-valor2; // calcula pendiente 2 


if (pend1>0 && pend2<0&& j>3&& valor1>510) //cuando las mismas cambian de signo alli estamos en el maximo (ademas forzamos a que haya por lo menos tres iteraciones para mas exactitud) 
{ 

corr=(valor2-512)*0.05341; // // 5.10/1023/1.4142/.066 = 0.05341( 66mv/Asensivilidad del sensor de correinte).Se restan 512 que es Vcc/2 o sea el punto Q del conversor 


Serial.println(); 
Serial.print ("V= "); 
Serial.print (volt,2); 

Serial.println(); 
Serial.print ("Ibinario= "); 
Serial.print (valor2); 

Serial.println(); 
Serial.print ("I= "); 
Serial.print (corr,2); 
Serial.println(); 


lcd.setCursor(0, 1); // Mueve el cursor a la linea de abajo 
lcd.print(corr*volt,0); // Muestra el valor de la potencia con cero decimal 
lcd.print(" W"); // Escribe la letra W 
delay(1000); // Demora un segundo para mostrar la lectura 

j=0; //se resetea j , se manda a setup nuevamente y se repite el ciclo 
setup(); 
} 
j--; // si sale por "no" ; se debe decrementar j una vez , ya que se incremento dos veces en la toma de los tres valores 

}

Que es esto

void tension() { 
       if(i>47) // dependiendo de donde inicie la toma de lecturas pueden llegar a hacerse mas de 50 iteracioens sin llegar al resultado 
        // de alli la pregunta de if>47 
       { 
        i=0; // si es cierto debe reiniciar !! 
        setup(); // MAL
      } 


void corriente() { 
     if(j>47) // dependiendo de donde inicie la toma de lecturas pueden hacerse mas de 50 iteracioens sin llegar al resultado 
     // de alli la pregunta de if>47 
    { 
    j=0; // si es cierto debe reiniciar 
     setup(); // MAL
}

Esos llamados a setup() no pueden hacerse. si tienes dudas, de que tu programa se cuelgue usa watchdog pero no llames a setup()

gracias sur siempre dando una mano para los que menos saben !..

bueno siguiendo tus sugerencias cambie el codigo ! pero tengo el siguiente problema primero paso a contar como tengo conectado la parte aisladora y rectificadora

la cosa es asi ! necesito medir corriente alterna de 220 v 60 hz para eso en la parte hadware utilizo
un trafo 220/12 v con un puente de diosdos en su salida para rectificar y un divisor de voltaje compuesto por una resistencia de 8.2k y 1k ,
el problema es el siguiente al tomar las lecturas lo que hago es poner esos valores en una matriz para poder tomar varios valores y sacar su promedio y quedarme con el mayor (pico), despues ese valor lo multiplico por el valor eficas que seria 4.45/1023*8.2/1/1.4142 = 0,0252
4,45= valor de referencia interno de arduino
1023= conversor adc
8.2 y 1 k = valor de resistencias
1,4142= valor de la raiz cuadrada de 2 !

el problema es que me da valores que no son los que esperaba por ejemplo 12 v y varia a 29 v no puedo obtener una lectura coehrente

dejo el nuevo codigo para que puedan observar y desirme

int i=0;              // para iterar
int lecturas[75];     // inicia matriz unidmensuinal con 75 posiciones
int valor1=0;
int valor2=0;
int valor3=0;
float valorf=0;
int pend1=0;
int pend2=0;


void  setup()
{

      //analogReference(EXTERNAL); // usado solo para referencia externa
  Serial.begin (9600);     //inicia comunicacion serial

   for(int cont=0;cont<75;cont++)      //hace un bucle for 
   {                                    // notese el delay para tomar casi dos ciclos
    lecturas[cont]=analogRead(A8);      
    delayMicroseconds(500);      
   }

       // for(int cont1=0;cont1<75;cont1++)     //hace un bucle for para mandar las 
       //{                                   //las lecturas al puerto serial para debuguear si es necesario
      //  Serial.println(lecturas[cont1]);
      //  }
}

void loop(){
   if(i>70)
  {
     i=0; 
     setup();
  }

    valor1=lecturas[i];
     i++;
    valor2=lecturas[i];
     i++;
    valor3=lecturas[i];
   
    pend1=valor2-valor1;
//  Serial.println();
//  Serial.print("Pend1: ");  para debuguear si es necesario
//  Serial.print(pend1);
//  delay(1000);
   
    pend2=valor3-valor2;
//   Serial.println();
//   Serial.print("Pend2: ");  para debuguear si es necesario
//   Serial.print(pend2);
//   delay(1000);
      
  if (pend1>0 && pend2<0&& i>3&&valor1>10) // se pregunta por valor1 > 10 ya que DURANTE el tiempo de rectificfacion
                                           // los valores de salida no son todos cero (no se porque!!!! ) ????
  {                                        // Y  darian salidas erroneas !!!! hacer un debug para verificar
   Serial.println();
   Serial.print ("V= ");  
   valorf=valor2*0,0252+0.7;   // 4.45/1023*8,2/1/1.4142 = 0.0338
                              // (4.45 tension de salida de usb =tension de alimenta de arduino ) mi caso (puede cambiar 
   Serial.print (valorf,2);     //  R1=8,2 ; R2=1k 
   Serial.print ("\t");
   Serial.print ("i=");
   Serial.print (i);
   Serial.println ();
   delay (1000); 
   i=0; 
   setup();
} 
i--; // decrementar i dos veces para tomar los siguientes tres vaores y repetir la rutina
}

Hola mafesolutions. Para mi las cuentas son Supongo que lees en A0, luego lo adaptas

Valor = VREF*analogRead(A0)/1023;

Tu Vo luego del divisor resistivo es Vo = 1/(8k2+1)*12V En realidad deberiamos quitarle 1.4 de dos diodos pero veamos como surge el resultado

Vo = 12/9.2 V = 1.30 V

SI tienes una Vref de 4.45 y tu valor maximo es 1.30v entonces estarás leyendo entorno a

1.30/4.45*1023= 299 cuentas Tu adc tiene 1024 pasos y tu lees solo hasta 1/3 MAL!!!!!!!! Debido a que uno de los detractores que se conseguir me ha hecho una observación respecto a este comentario MALLL voy a justificar que quiero decir. El rango de medición del AD va de 0 a 1023. Si solo usamos de 0 a 300 estamos desperdiciendo 723 cuentas mas. Lo logico es aprovechar casi todo el rango, algo que se logra modificando el divisor resistivo.

Mal el divisor resistivo. Debe ser 1/3 Resistencia de 2k y otra de 1k 2k en lugar de 8k2 y 1k. Veamos ahora

Vo = 1/(2k+1K) * 12v = 1/3*12=4V casi casi 4.45V

4.00/4.45*1023=919 te queda casi un 10% de margen.

Asi que por ahi mejorará la cuestion del divisor.

No miré el código, lo hago y te respondo.

tienes razon en eso me equivoque muchas gracias por ser siempre uno de los pocos que ayudan a resolver las dudas y enseñar a los que empezamos ! muchas gracias por estar en el foro ! va algo de karma :smiley:

surbyte: Hola mafesolutions. Para mi las cuentas son Supongo que lees en A0, luego lo adaptas

Valor = VREF*analogRead(A0)/1023;

Tu Vo luego del divisor resistivo es Vo = 1/(8k2+1)*12V En realidad deberiamos quitarle 1.4 de dos diodos pero veamos como surge el resultado

Vo = 12/9.2 V = 1.30 V

SI tienes una Vref de 4.45 y tu valor maximo es 1.30v entonces estarás leyendo entorno a

1.30/4.45*1023= 299 cuentas Tu adc tiene 1024 pasos y tu lees solo hasta 1/3 MAL!!!!!!!! Debido a que uno de los detractores que se conseguir me ha hecho una observación respecto a este comentario MALLL voy a justificar que quiero decir. El rango de medición del AD va de 0 a 1023. Si solo usamos de 0 a 300 estamos desperdiciendo 723 cuentas mas. Lo logico es aprovechar casi todo el rango, algo que se logra modificando el divisor resistivo.

Mal el divisor resistivo. Debe ser 1/3 Resistencia de 2k y otra de 1k 2k en lugar de 8k2 y 1k. Veamos ahora

Vo = 1/(2k+1K) * 12v = 1/3*12=4V casi casi 4.45V

4.00/4.45*1023=919 te queda casi un 10% de margen.

Asi que por ahi mejorará la cuestion del divisor.

No miré el código, lo hago y te respondo.

en bueno ahora creo que el problema que se me presenta proviene por el lado del codigo cuando pongo el cable del pin de salida del divisor de tension al A0 de arduino se queda tildado no muestra nada en el monitor seguramente es por como me dijiste los lamados a setup que no se pueden hacer pero como soluciono eso ? tendrias algun codigo mejor depurado para poder leer alterna ? con el cual me pueda orientar ? me parece que la falla esta en la toma de datos en la parte de lecturas y por eso queda trabado y no responde !!

otra pregunta al agregarle el puente de diodos o un diodo como rectificador convierto a media onda y obtengo aproximadamente la mitad de voltaje de la onda ! original ! osea unos 6 v aproximados ! eso tambien me puede trabar a arduino ?

gracuas surbyte por lo que vi sos de los pocos que responde en el foro !

Porque lo enviabas a setup? Quiero entender eso.

lo uso para que si en la lectura no se llegue a tomar un valor de promedio en las 75 muestras que se toma vuelva a hacer todo devuelta ! no se si lo hice bien o no es necesario ! pero creo que esa es la parte que falla

void loop(){


   if(i>70)
  {
     i=0; 
     setup();

Mira a ver si esto funciona correctamente.
Cambios a realizar:

  1. Resistencia de 2K en lugar de 8K2 y la de 1K la dejas como antes.
  2. debes instalar la librería Timer.h que la adjunto abajo.

El código

#include <LiquidCrystal.h> // Libreria para el display 
#include "Timer.h"

LiquidCrystal lcd (12, 11, 5, 4, 3, 2); 

const byte Vpin = A0;
const byte Ipin = A5;

float pot = 0; 

Timer timer;
volatile unsigned int contador  = 0;
volatile unsigned int MaxV = 0;
volatile unsigned int MaxI = 0;
volatile float volt = 0; // Se inician la varialbes para tension , corriente y potencia 
volatile float corr = 0; 
volatile bool Presento = false;

void setup() { 
 Serial.begin (9600); //inicia comunicacion serial 

 lcd.begin(16, 2); // declara lcd de dos lineas 
 lcd.print("Pot: "); // escribe la palabra Pot 

 int tickEventTensionCorriente = timer.every(1, MidoTensionCorriente); // cada 1 mseg invoca la rutina MidoTensionCorriente
} 

void loop(){ 
 timer.update();
 if (Presento) {
 Serial.println(); 
 Serial.print ("V= "); 
 Serial.print (volt,2); 

 Serial.println(); 
 Serial.print ("I= "); 
 Serial.print (corr,2); 
 Serial.println(); 


 lcd.setCursor(0, 1); // Mueve el cursor a la linea de abajo 
 lcd.print(corr*volt,0); // Muestra el valor de la potencia con cero decimal 
 lcd.print(" W"); // Escribe la letra W 
 Presento = false;
 }
} 



void MidoTensionCorriente() { 
    unsigned int Vmax, Imax;

 Vmax = analogRead(Vpin);
 if (Vmax > MaxV)
    MaxV = Vmax; // Vmax siempre es el valor máximo

 Imax = analogRead(Ipin);
 if (Imax > MaxI)
    MaxI = Imax; // Vmax siempre es el valor máximo

 if (++contador > 50) { // veo el maximo de 3 ciclos. 1 ciclo 16.6mseg. 
 volt = 9.44 * MaxV; // 9.44 = 3*4.45*MaxV/1.4142; 
 // 3 es el factor del divisor de tensión 1k y 2k
 corr = (MaxI-512)*0.05341;
 contador = 0; // 3 ciclos 3 x 16.6mseg = 50 mseg
 MaxV = 0;
 MaxI = 0;
 Presento = true;
 }   
}

Me dices como se comporta.
Los datos de corriente los puse como los tenías tu calculados.
Los cambios importanes son varios.
Yo busco el valor máximo de tensión y corriente usando un simple if(Valor>Max)
Si el Valor leido con el AD para tensión y corriente es mayor que el que tengo guardado me quedo con el.
Sino sigo…
No veo pendientes ni nada por el estilo.
NO uso los vectores tampoco.
Uso una librería que se llama Timer que debe inicializarse y que cada 1 mseg llama a MidoTensionCorriente.

Tambien busco el maximo en 3 ciclos totalizando 50 mseg = 3 x 16.66meg (1/60Hz) Al terminar pongo a cero mis contador y máximos y pongo en TRUE mi variable Presento, asi el serial puede enviar datos cada 50mseg.

Si es muy rapido puedo incrementar el periodo de cuenta. Multiplos de 3 ciclos.

Timer.zip (15.6 KB)

bueno sur byte le comento como me fue al momento

use el codigo que usted me compartio lo dejo al final del mensaje !, no hubo error no se cuelga nada pero me da valores medio raros ! saque una foto para poder mostrarle !

la conexion es la misma el fivisor resistivo ahora es 2k y 1k uso un diodo a la salida del trafo junto con una resistencia de 1 k para rectificar a media onda y leer con arduino
a la salida del divisor resistivo me da 2,68 con el tester en v y en la salida despues de rectificar 6v , dejo estos dalos para orientar mejor en mi explicacion y no confundirlo ! disculpe,

los valores que leo son estos conectando la salida del divisor al A0 de arduino

y sin conectar tambien me da estos valores

ya no se en que estoy errando ! dejo el codigo abajo que es el que usted me compartio !

#include <LiquidCrystal.h> // Libreria para el display 
#include "Timer.h"

LiquidCrystal lcd (12, 11, 5, 4, 3, 2); 

const byte Vpin = A0;
const byte Ipin = A5;

float pot = 0; 

Timer timer;
volatile unsigned int contador  = 0;
volatile unsigned int MaxV = 0;
volatile unsigned int MaxI = 0;
volatile float volt = 0; // Se inician la varialbes para tension , corriente y potencia 
volatile float corr = 0; 
volatile bool Presento = false;

void setup() { 
 Serial.begin (9600); //inicia comunicacion serial 

 lcd.begin(16, 2); // declara lcd de dos lineas 
 lcd.print("Pot: "); // escribe la palabra Pot 

 int tickEventTensionCorriente = timer.every(1, MidoTensionCorriente); // cada 1 mseg invoca la rutina MidoTensionCorriente
} 

void loop(){ 
 timer.update();
 if (Presento) {
 Serial.println(); 
 Serial.print ("V= "); 
 Serial.print (volt,2); 

 Serial.println(); 
 Serial.print ("I= "); 
 Serial.print (corr,2); 
 Serial.println(); 


 lcd.setCursor(0, 1); // Mueve el cursor a la linea de abajo 
 lcd.print(corr*volt,0); // Muestra el valor de la potencia con cero decimal 
 lcd.print(" W"); // Escribe la letra W 
 Presento = false;
 }
} 



void MidoTensionCorriente() { 
    unsigned int Vmax, Imax;

 Vmax = analogRead(Vpin);
 if (Vmax > MaxV)
    MaxV = Vmax; // Vmax siempre es el valor máximo

 Imax = analogRead(Ipin);
 if (Imax > MaxI)
    MaxI = Imax; // Vmax siempre es el valor máximo

 if (++contador > 50) { // veo el maximo de 3 ciclos. 1 ciclo 16.6mseg. 
 volt = 9.44 * MaxV; // 9.44 = 3*4.45*MaxV/1.4142; 
 // 3 es el factor del divisor de tensión 1k y 2k
 corr = (MaxI-512)*0.05341;
 contador = 0; // 3 ciclos 3 x 16.6mseg = 50 mseg
 MaxV = 0;
 MaxI = 0;
 Presento = true;
 }   
}

pd: lo redacte 3 veces al post porque no se todavia porque me redirigia al home del foro !

Porque un diodo. Usa un puente de diodos. Yo supuse que usarías un puente.
De todos modos el código espera valor máximos, no debería darte valores raros.
Lo que no se ve son las pantallas.
Has subido mal los enlaces. Mira en las normas del foro como subir imágines. Puedes usar www.tinypic.com para hacerlo

bueno ahi utilice un puente de diodos ac dc tengo el voltaje de 12 a la salida y en el divisor casi 4 v y aqui te dejo los resultados obtenidos en el monitor serie a las resitencias como dije antes del divisor son 2 y 1 k

lo que me parece raro es que al estar conectado en el puerto analogico voltaje en puerto serial se queda en 0 como muestro en esta imagen

|385x500

y cuando lo desconecto ! da estos valores medios raros !

|385x500

pd: doy mi palabra que apenas haga funcionar voy a hacer un tuto para dejarlo en el foro ya que no vi mucha info nuevamente gracias por la ayuda ! quedo en deuda

Bueno lo resolví por remoto. Habia un error muy tonto pero error al fin.

volt = (float)  0,01026455 * MaxV; // 9.44 = 3.7*4.95/1023.0*MaxV/1.4142;

Luego descubrimos que la tensión de salida pico era mayor que lo que toleraba el divisor de tensión porque arrojaba valores de fondo de escala (1023 cuentas) asi que cambiamos el divisor por un preset de 10k.

mafesolutions dará luego mayores explicaciones.

Bueno antes que nada gracias a surbyte por la paciencia y la ayuda recibida en este problema y en varios mas jejeje !

mi idea es poder armar un topic para el proyecto en su apartado correspondiente el cual hoy supongo terminare de editar !

como bien explico surbyte el error primero consistia en la declaracion del tipo de variable al cambiarla lo soluciono!pero luego descubrimos que el v pico era mayor y superaba al divisor entonces procedimos a cambiarlo por una resistencia de 2.7k y otra de 1k (el preset lo usamos ya que no tenia resistencia de ese valor en especifico ! (preset=10k))

ahora lo siguiente como quedo armado el hadware
de los 220v un transformador ac-ac de 220/12 con un puente de diodos para rectificar a onda completa el divisor de tension , va de 2.7 k a otra resistencia de 1 k el codigo lo dejo abajo ! no pongo fotos ya que cuando termine de editar el topic va a estar en proyecto mejor detallado

otra vez mas gracias a surbyte por su atencion y muy buena onda ! encantado de poder conversar y aprender de gente que sabe ! y esta dispuesta a enseñar

CODIGO

#include <LiquidCrystal.h>
#include "Timer.h"


LiquidCrystal lcd (12, 11, 5, 4, 3, 2);

const byte Vpin = A9;
const byte Ipin = A5;


Timer timer;
volatile unsigned int contador = 0;
volatile unsigned int valor;
volatile unsigned int MaxV = 0 ;
volatile unsigned int MaxI = 0 ;
volatile float volt = 0;
volatile float corr = 0;
volatile bool Presento = false;



void setup() {
  Serial.begin(9600);
  lcd.begin(20, 4);
       int tickEventTensionCorriente = timer.every(1, MidoTensionCorriente);
}

void loop() {
  char buf[20], str[6];
      timer.update();
          if (Presento){
            sprintf(buf, "V= %s %d", dtostrf(volt, 4,2, str), valor);
                Serial.println(buf);
                
                Presento = false;
}
}

void MidoTensionCorriente (){
  unsigned int Vmax , Imax;
  
     Vmax= analogRead(Vpin);
       valor = Vmax;
         if (Vmax > MaxV)
           MaxV = Vmax;
  
  
 Imax = analogRead(Ipin);
   if (Imax > MaxI)
      MaxI = Imax; // Vmax siempre es el valor máximo
  
   if (++contador > 50) { // veo el maximo de 3 ciclos. 1 ciclo 16.6mseg. 
   float factor = 0.01288099; //(3.2)*4.95/1023.0/1,4142;
     volt = (float) (factor * MaxV*18.0); 
     // 3 es el factor del divisor de tensión 1k y 2k
     corr = (float) (MaxI-512)*0.05341;
     contador = 0; // 3 ciclos 3 x 16.6mseg = 50 mseg
     MaxV = 0;
     MaxI = 0;
     Presento = true;
     
 }
}

gracias foro :smiley:

Recuenda sacar la relacion de transformación midiendo tensión de entrada y de salida y todo eso debes afectarlo al factor calculado para que te de la tensión de entrada, no la que mides a la salida del secundario.