Autor Tema: Un bocata de relés, por favor. Novato empezando...  (Leído 6865 veces)

0 Usuarios y 1 Visitante están viendo este tema.

peperfus

  • Visitante
Re: Un bocata de relés, por favor. Novato empezando...
« Respuesta #60 en: 12-11-2017, 20:25 (Domingo) »
Ya he estado jugando con el relé de estado sólido. Mola mucho y la velocidad de reacción es alucinante.







La bombilla no se ha fundido  :D

Me he equivocado en el orden de los vídeos. El primero es el más rápido de los dos, prácticamente el parpadeo es inapreciable.


« Última modificación: 12-11-2017, 20:28 (Domingo) por peperfus »

peperfus

  • Visitante
Re: Un bocata de relés, por favor. Novato empezando...
« Respuesta #61 en: 12-11-2017, 21:02 (Domingo) »
Ficht, esta idea tuya que te montaste, me mola mucho. Estoy pensando que igual hago algo así. Lo llamaría un "panel de control". Le pondría unos enchufes de superficie, 4 para manejarlos con el módulo de 4 relés conectado a la pcf8574, todo sobre una tabla de madera con unos ganchos para colgar en la pared.


(Imagen de Ficht)

Lo del panel ese de botones táctiles que tienes ahí arriba a la derecha, supongo que es para poder activar y desactivar los relés manualmente, ¿correcto? ¿al final lo conseguiste? ¿Podrías explicar como lo hiciste? Me parece muy interesante, pero no veo la forma de combinar ambos métodos al mismo tiempo (pcf8574 + panel botones). Gracias.
Supongo que con la instrucción i2cget, el bus y el número de pcf8574 lees el estado de sus pines y con eso puedes saber qué botón se ha pulsado, pero.... supongo que por eso preguntabas si había alguna manera de detectar que se ha pulsado un botón, ¿no?; para no tener que hacer un i2cget cada x segundos, ¿es así? ¿Al final lo conseguiste? ¿Cómo lo hiciste?

Por cierto, ¿qué es ese otro circuito que hay a la derecha del todo, qué es lo que hace? Ese que marca unos dígitos con 3.4 ??
« Última modificación: 12-11-2017, 21:16 (Domingo) por peperfus »

Ficht

  • Visitante
Re: Re: Un bocata de relés, por favor. Novato empezando...
« Respuesta #62 en: 12-11-2017, 21:33 (Domingo) »
Ficht, esta idea tuya que te montaste, me mola mucho. Estoy pensando que igual hago algo así. Lo llamaría un "panel de control". Le pondría unos enchufes de superficie, 4 para manejarlos con el módulo de 4 relés conectado a la pcf8574, todo sobre una tabla de madera con unos ganchos para colgar en la pared.


(Imagen de Ficht)

Lo del panel ese de botones táctiles que tienes ahí arriba a la derecha, supongo que es para poder activar y desactivar los relés manualmente, ¿correcto? ¿al final lo conseguiste? ¿Podrías explicar como lo hiciste? Me parece muy interesante, pero no veo la forma de combinar ambos métodos al mismo tiempo (pcf8574 + panel botones). Gracias.

Por cierto, ¿qué es ese otro circuito que hay a la derecha del todo, qué es lo que hace? Ese que marca unos dígitos con 3.4 ??
Bueno, hasta donde se, para que el panel sea efectivo hay que definir el puerto I2C en el dts de la placa, para definir botones de entrada, ya sea haciendo GPIO's en el 8574 o definiendo en tablero I2C tal cual, para que cree eventos recogidos en el kernel, esto lo tengo ahí aparcao...
El regulador que marca 3.y pico alimenta un LCD que jugaba con el, pero montando un puerto SPI, también está aparcao...
De lo contrario habría que hacer rodar un script que leyera constantemente teclado o gpios y hacer el trabajo, pero eso no es eficiente.



Enviado desde mi PRA-LX1 mediante Tapatalk


Desconectado peperfus

  • ****
  • Mensajes: 71
Re:Un bocata de relés, por favor. Novato empezando...
« Respuesta #63 en: 27-10-2018, 18:53 (Sábado) »
SCRIPT que utilizo para modificar el estado de una plaquita de 4 relés, conectados al bus expansor: PCF8574. En realidad se puede utilizar para cualquier propósito, siempre para los 4 pines primeros de la expansora.
Requiere la utilidad bc (se puede instalar fácilmente desde software con luci, o con opkg...)

Lo he probado y creo que va bien en todos los casos. Si alguien descubre algún bug, etc...., comentarios son bienvenidos. Así como críticas (siempre constructivas), mejoras, etc...

Código: [Seleccionar]
#!/bin/sh

# ACTIVA O DESACTIVA UN RELE, RESPETANDO EL ESTAOD DE LOS DEMAS
# SINTAXIS:
# rele.sh num ON/OFF
# rele.sh num 1/0
# siendo num el numero de rele que queremos modificar
# <PUBLICIDAD>
# www.formulamanager.com Nuevo juego online manager de carreras.
# </PUBLICIDAD>



if [ $# -eq 2 ]; then
  #Nos devuelve en hexadecimal:
  prevState_bruto=$(i2cget -y 0 0x20)
  # formatearlo, quitarle el 0x y pasar a mayuscula,
  # porque el BC es muy tiquismiquis
  # Ademas solo nos interesa el primer digito
  # (los primeros 4 bits)
#echo "PREVSTATE=$prevState_bruto"
  prevState=$(echo $prevState_bruto|cut -c 3 | tr [a-z] [A-Z])
#echo "PREVSTATE=$prevState"
  # convertirlo a binario:
  ESTADOBIN_=$(echo "ibase=16;obase=2;$prevState" | bc)
  # rellenar con ceros segun sea necesario:
  ESTADOBIN=$(printf "%04d" $ESTADOBIN_)


#echo "PREVSTATE=$prevState"
#echo "ESTADOBIN=$ESTADOBIN"


  case $1 in
    1)
      case $2 in
        ON|on|On|oN|1) newState=$(echo $ESTADOBIN | cut -c 1-3)"0"
        ;;
        OFF|off|Off|oFF|0) newState=$(echo $ESTADOBIN | cut -c 1-3)"1"
        ;;
      esac
    ;;
    2)
      newState_izq=$(echo $ESTADOBIN | cut -c 1-2)
      newState_der=$(echo $ESTADOBIN | cut -c 4)
      case $2 in
        ON|on|On|oN|1)
          newState=$newState_izq"0"$newState_der
        ;;
        OFF|off|Off|oFF|0)
          newState=$newState_izq"1"$newState_der
        ;;
      esac
    ;;
    3)
      newState_izq=$(echo $ESTADOBIN | cut -c 1)
      newState_der=$(echo $ESTADOBIN | cut -c 3-4)
      case $2 in
        ON|on|On|oN|1)
          newState=$newState_izq"0"$newState_der
        ;;
        OFF|off|Off|oFF|0)
          newState=$newState_izq"1"$newState_der
        ;;
      esac
    ;;
    4)
      newState_der=$(echo $ESTADOBIN | cut -c 2-4)
      case $2 in
        ON|on|On|oN|1) newState="0"$newState_der
        ;;
        OFF|off|Off|oFF|0) newState="1"$newState_der
        ;;
      esac
    ;;
    *)
      echo "SINTAXIS MAL"
    ;;
  esac




  # convertir nuevoestado a HEXADECIMAL:
  # primero a decimal por bc tiquismiquis:
   ESTADODEC=$(echo "ibase=2; $newState"|bc)
   ESTADOHEX=$(echo "obase=16; $ESTADODEC"|bc)
   ESTADOHEXOK=0x$ESTADOHEX
#echo ESTADOBIN=$ESTADOBIN
#echo newState=$newState
#echo ESTADODEC=$ESTADODEC
#echo ESTADOHEXOK=$ESTADOHEXOK
#echo "i2cset -y 0 0x20 $ESTADOHEXOK"F
 i2cset -y 0 0x20 "$ESTADOHEXOK"F
else
  echo "SINTAXIS rele.sh numEnchufe ON/OFF"
fi
« Última modificación: 23-11-2018, 13:17 (Viernes) por peperfus »

Desconectado Ficht

  • **
  • Mensajes: 16
Re:Un bocata de relés, por favor. Novato empezando...
« Respuesta #64 en: 27-10-2018, 23:11 (Sábado) »
Hola @peperfus.

Yo es que no lo hago así a pelo, resulta altamente engorroso (por lo menos para mi)
yo lo que hago es cargar el módulo al kernel y que el haga los cálculos.... (lo cargo en el arranque /etc/rc.local)

Código: [Seleccionar]
echo pcf8574 0x39 > /sys/bus/i2c/devices/i2c-0/new_device
De este modo, ya los tratas como 8 GPIO nuevos en gpiochipX, y para simplificar el uso de ellos uso este script de la siguiente manera; /etc/gpio 3 out 0 para encender el relé o /etc/gpio  3 out 1 para apagar el relé

Código: [Seleccionar]
#!/bin/sh
 
show_usage()
{
    printf "\ngpio.sh <gpio pin number> [in|out [<value>]]\n"
}
 
if [ \( $# -eq 0 \) -o \( $# -gt 3 \) ] ; then
    show_usage
    printf "\n\nERROR: incorrect number of parameters\n"
    exit 255
fi
 
GPIOBASE=`cat /sys/class/gpio/gpiochip*/base | head -n1`
GPIO=`expr $1 + $GPIOBASE`
 
#doesn't hurt to export a gpio more than once
(echo $GPIO > /sys/class/gpio/export) >& /dev/null
 
if [  $# -eq 1 ] ; then
   cat /sys/class/gpio/gpio$GPIO/value
   exit 0
fi
 
if [ \( "$2" != "in" \) -a  \( "$2" != "out" \) ] ; then
    show_usage
    printf "\n\nERROR: second parameter must be 'in' or 'out'\n"
    exit 255
fi
 
echo $2 > /sys/class/gpio/gpio$GPIO/direction
 
if [  $# -eq 2 ] ; then
   cat /sys/class/gpio/gpio$GPIO/value
   exit 0
fi
 
 
VAL=$3
 
if [ $VAL -ne 0 ] ; then
    VAL=1
fi
 
echo $VAL > /sys/class/gpio/gpio$GPIO/value 
nota: el script ya exporta el gpio y tu lo mismo lo declaras out que in según te interese en la instrucción en si con el script, también te permite tratar todos los gpio's como 1, 2, 3, etc... hasta el ultimo es decir, gpio 1 y no gpio 477.

Luego con un simple condicional => a un boton xxx  controlas el relé (mirate triggerhappy o procd buttons)

Código: [Seleccionar]
#!/bin/sh
A=`cat /sys/class/gpio/gpio479/value`
                           
if [ $A -ne 1 ];then       
        /etc/gpio 7 out 1
elif [ $A -eq 1 ];then     
        /etc/gpio 7 out 0
else                       
        /etc/gpio 7 out 1                 
fi                     
Es la forma más cómoda que se me ocurre a mi, no se si tienes tu otra idea....
Saludos.

Desconectado peperfus

  • ****
  • Mensajes: 71
Re:Un bocata de relés, por favor. Novato empezando...
« Respuesta #65 en: 29-10-2018, 23:22 (Lunes) »
Hola, Ficht
Mucho mejor tu forma, pero ya que había empezado, me he encabezonado con terminar el script, hasta que lo he conseguido hacer funcionar.
Cualquier día pruebo lo que comentas, que tiene muy buena pinta. No sabía que se podía hacer eso. (En realidad soy muy novato en linux todavía..., pero poco a poco aprendiendo cosillas).

Saludos y gracias por compartir !!

Desconectado raphik

  • **
  • Mensajes: 32
Re:Un bocata de relés, por favor. Novato empezando...
« Respuesta #66 en: 30-10-2018, 14:41 (Martes) »
...
El SCRIPT que utilizo para modificar el estado de una plaquita de 4 relés, conectados al bus expansor: PCF8574. En realidad se puede utilizar para cualquier propósito, siempre para los 4 pines primeros de la expansora.
Requiere la utilidad bc
...

En realidad se puede hacer sin la utilidad bc.

Para recoger el estado de los relés:
Código: [Seleccionar]
DISPOSITIVO=0x20
prevState=$(printf "%d" $(i2cget -y 0 $DISPOSITIVO))

Para establecer el estado de los relés:
Código: [Seleccionar]
DISPOSITIVO=0x20
$(printf "i2cset -y 0 %s 0x%02x\n" $DISPOSITIVO $lastState)

El valor de lastState se calcula a partir de la variable prevState y del parámetro $1.
Se utiliza lógica negativa. Es decir, el 0 activa el relé y el 1 lo desactiva.

Para ACTIVAR:
Código: [Seleccionar]
# ON => a AND NOT(b)
lastState=$(( $prevState & $(( ~$(( 2**$1 )) )) ))

Para DESACTIVAR:
Código: [Seleccionar]
# OFF => a OR b
lastState=$(( $prevState | $(( 2**$1 )) ))

El script completo.

rele.sh
Código: [Seleccionar]
#!/bin/sh                                                                                                       

DISPOSITIVO=0x20                                                                                               

verSintaxis(){
  printf "\n  rele.sh v1.0\n"
  printf "\n  SINTAXIS ./rele.sh ENCHUFE ESTADO"
}                                                                                                               

if [ $# -ne 2 ]; then
  verSintaxis
  printf "\n  ERROR: Se requieren dos par..metros\n\n"
  exit
fi

if ! [ "$1" -eq "$1" ] 2>/etc/null || [ "$1" -lt 0 ] || [ "$1" -gt 7 ]; then
  verSintaxis
  printf "\n  ERROR: ENCHUFE = 0 .. 7\n\n"
  exit
fi

MANIOBRA=$(echo $2 | tr [a-z] [A-Z])

if [ $MANIOBRA != "ON" ] && [ $MANIOBRA != "1" ] && [ $MANIOBRA != "OFF" ] && [ $MANIOBRA != "0" ]; then
  verSintaxis
  printf "\n  ERROR: ESTADO = OFF | ON | 0 | 1\n\n"
  exit
fi

# Leer estado previo
prevState=$(printf "%d" $(i2cget -y 0 $DISPOSITIVO))
                                                                                                               
# Activar
if [ $MANIOBRA == "ON" ] || [ $MANIOBRA == "1" ]; then
  # printf "Activar #$1\n"
  # ON => a AND NOT(b)
  lastState=$(( $prevState & $(( ~$(( 2**$1 )) )) ))
fi                                                                                                             

# Desactivar
if [ $MANIOBRA == "OFF" ] || [ $MANIOBRA  == "0" ]; then
  # printf "Desactivar #$1\n"
  # OFF => a OR b
  lastState=$(( $prevState | $(( 2**$1 )) ))
fi

# Enviar orden a los relés
$(printf "i2cset -y 0 %s 0x%02x\n" $DISPOSITIVO $lastState)
# Para visualizar el estado inicial y final de los relés descomentar las dos líneas siguientes
# printf "Estado inicial: "; awk -v var="$prevState" 'BEGIN { for (i = 0; i <= 7; i++) { printf int(var/2^(7-i))%2 } print }'
# printf "Estado - final: "; awk -v var="$lastState" 'BEGIN { for (i = 0; i <= 7; i++) { printf int(var/2^(7-i))%2 } print }'

La sintaxis de llamada al script es
Código: [Seleccionar]
./rele.sh 0 on   # Activar relé P0
./rele.sh 5 off  # Desactivar relé P5

¿Y si tuviéramos que manejar más de ocho relés?

Para manejar más de ocho relés hay que usar tarjetas expansoras adicionales. Sería necesario desincrustar del código la dirección i2c y pasarla como parámetro.

La sintaxis quedaría así
Código: [Seleccionar]
./rele.sh 0x20 0 on   # Activar relé P0 de la expansora 0x20
./rele.sh 0x21 5 off  # Desactivar relé P5 de la expansora 0x21

Saludos.
« Última modificación: 01-11-2018, 09:49 (Jueves) por raphik »

Desconectado peperfus

  • ****
  • Mensajes: 71
FANTASMAS
« Respuesta #67 en: 18-11-2018, 12:36 (Domingo) »
Muchas gracias por los comentarios y las opciones propuestas.

Comento ahora porque me está pasando una cosa absolutamente fantasmagórica con mi script. (Y no exagero, me he roto la cabeza durante horas y no entiendo qué coj... está pasando).
Aviso que esto es para valientes  ;D

El misterio es que mi script, en teoría (y en la práctica), aún siendo menos eficiente que los vuestros.... funciona perfectamente:
Enciende y apaga cada relé independientemente de los demás.
Sin embargo.... hay algún caso particular, según el orden de encendido que hace que el comando cut falle:
Me explico breve y directamente:

ESTADOBIN=1010
Si a eso le aplico un cut -c 2-4 debería devolverme 010, verdad?
Pues me devuelve 8  ??? ??? ??? ??? ??? ??? ??? ??? ??? ??? ??? ??? ??? WTF.

Le he puesto un par de echos en el script, antes del comando cut, para asegurarme de que el contenido de la variable es exactamente correcto. Y LO ES.
Este es el trozo FANTASMA (fallo totalmente inexplicable, sucesos paranormales) del script:

Código: [Seleccionar]
echo "ESTADOBIN en 4 es $ESTADOBIN"
      newState_BRUTO_der=$(($(echo $ESTADOBIN | cut -c 2-4)))
      newState_BRUTO_der_OK=$(printf "%03d" $newState_BRUTO_der)

echo "_____________"

  echo "newState_BRUTO_der $newState_BRUTO_der (cut 2-4)"
  echo "newState_BRUTO_der_OK $newState_BRUTO_der_OK printf %03d"

echo "_____________"

Y esta es la salida:
Código: [Seleccionar]
ESTADOBIN en 4 es 1010
_____________
newState_BRUTO_der 8 (cut 2-4)
newState_BRUTO_der_OK 008 printf %03d
_____________

Me joden muchísimo estas cosas, porque deja mi razonamiento y mi lógica por los suelos. Es como si un duendecillo se estuviera cachondeando de mí.

Si algún valiente e intrépido detective  no le tiene miedo a los expedientes X y se atreve a enfrentarse a lo desconocido.... que me avise. Lo invitaré a una cerveza con mucho gusto.

El caso es que el relé número 4 se enciende y apaga perfectamente, de forma independiente. Es cuando hago cierta secuencia de encendido y apagado de otros relés cuando se produce el inexplicable fallo del cut. Esta es la secuencia que produce fallo:
./rele.sh 1 on (OK, perfecto)
./rele.sh 2 on (OK, perfecto)
./rele.sh 3 on (OK, perfecto)
./rele.sh 2 off (OK, perfecto)
./rele.sh 4 on  SUCESO PARANORMAL. cut debe devolver 010, en cambio, me devuelve 8  :P
Totalmente inexplicable.
« Última modificación: 18-11-2018, 12:39 (Domingo) por peperfus »

Desconectado Ficht

  • **
  • Mensajes: 16
Re:Un bocata de relés, por favor. Novato empezando...
« Respuesta #68 en: 18-11-2018, 16:10 (Domingo) »
Hola @peperfus

Tu estás usando el AR-5387un ?
Yo tengo en uso este "AR-5387UN"  un "VH4032N" y otro "HG556a" también con reles en bus I2C, no se si te ayuda pero a mi caso parece ser la fuente de la placa del AR-5387un,  cuando se producen "armónicos" en la corriente eléctrica de mi casa, el estado de los pcf8574 del bus, se ve afectado en este router (cambia de estado a voluntad) "fantasmagórico"....  en cambio, no pasa en el VH4032N ni en el HG556A (por supuesto que he ido descartando tomas de conexiones de otros puntos de la casa y temas así) la secuencia me ocurre con las luces de la cocina, que al encenderlas o apagarlas, producen un estado "como de flotación en los pines del pcf8574 (en el AR-5387un)", al repetir el script dos o tres veces  se corrige el estado.
Buscando la parte positiva, esto me ha servido para ver éste fallo en mi casa, que he ido afinando y ya solo ocurre aveces y solo al encender la cocina (en un tema aveces complejo)

Desconectado eduperez

  • **
  • Mensajes: 19
Re:FANTASMAS
« Respuesta #69 en: 18-11-2018, 21:39 (Domingo) »
Sin embargo.... hay algún caso particular, según el orden de encendido que hace que el comando cut falle:
Me explico breve y directamente:

ESTADOBIN=1010
Si a eso le aplico un cut -c 2-4 debería devolverme 010, verdad?
Pues me devuelve 8  ??? ??? ??? ??? ??? ??? ??? ??? ??? ??? ??? ??? ??? WTF.

Le he puesto un par de echos en el script, antes del comando cut, para asegurarme de que el contenido de la variable es exactamente correcto. Y LO ES.
Este es el trozo FANTASMA (fallo totalmente inexplicable, sucesos paranormales) del script:

Código: [Seleccionar]
echo "ESTADOBIN en 4 es $ESTADOBIN"
      newState_BRUTO_der=$(($(echo $ESTADOBIN | cut -c 2-4)))
      newState_BRUTO_der_OK=$(printf "%03d" $newState_BRUTO_der)

echo "_____________"

  echo "newState_BRUTO_der $newState_BRUTO_der (cut 2-4)"
  echo "newState_BRUTO_der_OK $newState_BRUTO_der_OK printf %03d"

echo "_____________"

Si ejecutas "$(echo $ESTADOBIN | cut -c 2-4)", el resultado es directamente "010", no necesitas más.
Si ejecutas "$(($(echo $ESTADOBIN | cut -c 2-4)))", entonces estás pidiendo que se interprete "(010)", pero los números que comienzan por 0 se asume que están en octal, y "010" en octal es "8".

Desconectado peperfus

  • ****
  • Mensajes: 71
Re:Un bocata de relés, por favor. Novato empezando...
« Respuesta #70 en: 18-11-2018, 23:00 (Domingo) »
eduperez, MIL GRACIAS.

No tengo prácticamente ni idea de la sintaxis del $ y los paréntesis para asignar valores a las variables....
Lo vi por ahí en Internet, lo probé y como me funcionaba, ya suponía que era correcto, pero ya he visto que no.

Lo he corregido y ya funciona perfectamente.  >:( >:( >:( >:(

Fantasma cazado  ;D ;D ;D
Voy a corregir el script que puse en un post anterior por si alguien lo quiere utilizar, para que no se lleve el mismo error.

Gracias otra vez. Si hay la posibilidad, te invito a una cerveza.

(Ficht, a ti también te invito, jejejeje)
« Última modificación: 19-11-2018, 11:49 (Lunes) por peperfus »

Desconectado eduperez

  • **
  • Mensajes: 19
Re:Un bocata de relés, por favor. Novato empezando...
« Respuesta #71 en: 20-11-2018, 15:13 (Martes) »
eduperez, MIL GRACIAS.

No tengo prácticamente ni idea de la sintaxis del $ y los paréntesis para asignar valores a las variables....
Lo vi por ahí en Internet, lo probé y como me funcionaba, ya suponía que era correcto, pero ya he visto que no.

Lo he corregido y ya funciona perfectamente.  >:( >:( >:( >:(

Fantasma cazado  ;D ;D ;D
Voy a corregir el script que puse en un post anterior por si alguien lo quiere utilizar, para que no se lleve el mismo error.

Gracias otra vez. Si hay la posibilidad, te invito a una cerveza.

(Ficht, a ti también te invito, jejejeje)

En el fondo no es tan complicado...
  • "variable=$(comando)" significa "ejecuta el comando y asigna el resultado a la variable"; si haces "resultado=$(date)" tendrás en "resultado" la fecha.
  • "variable=$((expresión))" significa "calcula el resultado de la expresión y asigna el resultado a la variable"; si haces "resultado=$((1+2))" tendrás en "resultado" el valor "3".
  • Entonces, "variable=$(($(comando)))" significa "ejecuta el comando, interpreta el resultado como una expresión, y asigna el resultado a la variable"; y el problema era que el resultado del comando era una expresión que se interpretaba como un número en octal, nada más.

Te agradezco la cerveza, la próxima vez que me tome una lo haré a tu salud.