{"id":170,"date":"2016-03-19T23:38:04","date_gmt":"2016-03-19T22:38:04","guid":{"rendered":"http:\/\/lab.fawno.com\/?p=170"},"modified":"2022-03-07T01:34:15","modified_gmt":"2022-03-07T00:34:15","slug":"","status":"publish","type":"post","link":"https:\/\/lab.fawno.com\/en\/2016\/03\/19\/frontal-de-descodificador\/","title":{"rendered":"","raw":""},"content":{"rendered":"","protected":false,"raw":""},"excerpt":{"rendered":"","protected":false,"raw":""},"author":1,"featured_media":144,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_coblocks_attr":"","_coblocks_dimensions":"","_coblocks_responsive_height":"","_coblocks_accordion_ie_support":"","_editorskit_title_hidden":false,"_editorskit_reading_time":0,"_editorskit_typography_data":[],"_editorskit_blocks_typography":"","_editorskit_is_block_options_detached":false,"_editorskit_block_options_position":"{}","_es_post_content":"\n

Revisando en el trastero todo aquello que me pudiera servir para mis arduinos<\/a>, me encontr\u00e9 alg\u00fan que otro descodificador. De uno de ellos obtuve este panel:<\/p>\n\n\n\n

\"Panel<\/a>
Panel frontal descodificador (Frontal)<\/figcaption><\/figure><\/div>\n\n\n\n

B\u00e1sicamente tenemos ocho botones, un display de 4 d\u00edgitos, dos leds bicolores (rojo-verde) y tres de color (rojo, amarillo, verde) y un receptor IR con su mando a distancia... todo por el m\u00f3dico precio de averiguar c\u00f3mo demonios controlar esto con un Arduino. Ten\u00eda la esperanza de que al tener tantos componentes en la placa y s\u00f3lo un bus de diez l\u00edneas como \u00fanica comunicaci\u00f3n con la placa base ser\u00eda posible controlar el panel de forma sencilla con Arduino.<\/p>\n\n\n\n

As\u00ed que lo primero que hice fue revisar la trasera del frontal para ver qu\u00e9 circuitos integrados (aka garrapatas negras) lleva el trasto:<\/p>\n\n\n\n

\"Panel<\/a>
Panel frontal descodificador (Trasera)<\/figcaption><\/figure><\/div>\n\n\n\n

En la foto no se observa, pero con una lupa y la iluminaci\u00f3n adecuada pude comprobar que los dos \u00fanicos circuitos integrados son el MM74HC595M:<\/p>\n\n\n\n

\"MM74HC959M\"<\/a>
MM74HC959M<\/figcaption><\/figure><\/div>\n\n\n\n

Una r\u00e1pida b\u00fasqueda nos da como resultado que el MM74HC595M<\/a> es un registro de desplazamiento de 8 bits (8bits Shift Register) del que hay sobrada documentaci\u00f3n<\/a> con respecto a c\u00f3mo controlarlo con Arduino<\/a>. As\u00ed que mi primera intuici\u00f3n empezaba a cobrar fuerza.<\/p>\n\n\n\n

Sin embargo necesitaba saber el esquema para poder averiguar c\u00f3mo controlar el panel. As\u00ed que en dos o tres d\u00edas ya ten\u00eda los primeros esquemas a mano de la parte de los cuatro d\u00edgitos de siete segmentos y en dos o tres d\u00edas m\u00e1s el esquema definitivo<\/a>:<\/p>\n\n\n\n

\"Panel<\/a>
Panel frontal descodificador (esquema)<\/figcaption><\/figure><\/div>\n\n\n\n

Del esquema se puede ver que con s\u00f3lo 8 cables (6 si descontamos Vcc y GND) podemos controlar los 4 d\u00edgitos de siete segmenos, los 5 leds (dos de ellos bicolor), recibir las se\u00f1ales del mando a distancia y saber qu\u00e9 pulsador es el que se ha accionado.<\/p>\n\n\n\n

Lo m\u00e1s f\u00e1cil es utilizar el receptor de infrarrojos, ya que con conectar la alimentaci\u00f3n (pin 1 del panel a GND y pin 9 a +5V) y conectar el pin 2 del panel a una entrada digital del Arduino ya podemos jugar<\/a> con un mando a distancia<\/a>.<\/p>\n\n\n\n

Evidentemente para jugar con el resto de elementos hay que pensar un poco m\u00e1s. Por ejemplo, algo que en los ejemplos y circuitos que he visto con Arduino y el 74595 suelen obviar el pin Enable<\/em> de estos chips. El panel lo utiliza y le da salida, siendo muy \u00fatil pues si en setup lo ponemos en HIGH<\/em> antes de poner el panel en su configuraci\u00f3n inicial (la que decidamos que deba ser) y una vez establecida dicha configuraci\u00f3n ponemos el Enable<\/em> a LOW<\/em> habremos tenido el panel completamente apagado (los leds y los segmentos de los d\u00edgitos) hasta obtener una situaci\u00f3n estable y conocida:<\/p>\n\n\n\n

void setup() {\n  pinMode(latchPin, OUTPUT);\n  pinMode(clockPin, OUTPUT);\n  pinMode(enablePin, OUTPUT);\n  pinMode(dataPin, OUTPUT);\n  pinMode(swPin, INPUT);\n\n  \/\/ Desactivamos las salidas de los 74595\n  digitalWrite(enablePin, HIGH);\n\n  \/\/ Establecemos la condici\u00f3n inicial del Panel\n  digitalWrite(latchPin, LOW);\n  shiftOut(dataPin, clockPin, LSBFIRST, 0b00001111);\n  shiftOut(dataPin, clockPin, LSBFIRST, 0b00110000);\n  digitalWrite(latchPin, HIGH);\n\n  \/\/ Activamos las salidas de los 74595\n  digitalWrite(enablePin, LOW);\n}<\/pre>\n\n\n\n

La verdad, el resultado es muy chulo, sobre todo por las opciones que me da sin tener que cablear o soldar nada:<\/p>\n\n\n\n

\nhttps:\/\/www.youtube.com\/watch?v=GygqIUF_WFI\n<\/div><\/figure>\n\n\n\n

Y el c\u00f3digo completo:<\/p>\n\n\n\n

const byte Digits[] = {\n  0b00001110, \/\/ Digit 0\n  0b00001101, \/\/ Digit 1\n  0b00001011, \/\/ Digit 2\n  0b00000111, \/\/ Digit 3\n};\n\nconst byte swMask = 0b00001111;\n\nconst byte buttons[] = {\n  0b10001110, \/\/ 0 SW1 POWER\n  0b10001101, \/\/ 1 SW2 UP\n  0b10001011, \/\/ 2 SW3 DOWN\n  0b10000111, \/\/ 3 SW4 RADIO\n  0b01001110, \/\/ 4 SW5 MENU\n  0b01001101, \/\/ 5 SW6 LEFT\n  0b01001011, \/\/ 6 SW7 YES\n  0b01000111, \/\/ 7 SW8 RIGHT\n};\n\nconst byte dec7seg[] = {\n  0b00111111, \/\/ 0\n  0b00000110, \/\/ 1\n  0b01011011, \/\/ 2\n  0b01001111, \/\/ 3\n  0b01100110, \/\/ 4\n  0b01101101, \/\/ 5\n  0b01111101, \/\/ 6\n  0b00000111, \/\/ 7\n  0b01111111, \/\/ 8\n  0b01101111, \/\/ 9\n};\n\nconst byte LedsRight = 0b00001111;\nconst byte LedsRYG_G = 0b00100001;\nconst byte LedsRYG_Y = 0b00100010;\nconst byte LedsRYG_R = 0b00101000;\nconst byte LedsRG_G1 = 0b00010001;\nconst byte LedsRG_R1 = 0b00010010;\nconst byte LedsRG_G4 = 0b00010100;\nconst byte LedsRG_R4 = 0b00011000;\n\n\nconst int dataPin = 11;  \/\/ 74HC595 Pin 14 (GRIS)\nconst int latchPin = 10; \/\/ 74HC595 Pin 12 (VERDE)\nconst int clockPin = 9;  \/\/ 74HC595 Pin 11 (MORADO)\nconst int enablePin = 8; \/\/ 74HC595 Pin 13 (MARRON)\nconst int swPin = 7;     \/\/ AZUL\n\nbyte LedsRG = 0b00000000;\nbyte LedsRYG = 0b00000000;\n\nint wait = 0;\n\nvoid setup() {\n  pinMode(latchPin, OUTPUT);\n  pinMode(clockPin, OUTPUT);\n  pinMode(enablePin, OUTPUT);\n  pinMode(dataPin, OUTPUT);\n  pinMode(swPin, INPUT);\n  digitalWrite(enablePin, HIGH);\n  digitalWrite(latchPin, LOW);\n  shiftOut(dataPin, clockPin, LSBFIRST, 0b00001111);\n  shiftOut(dataPin, clockPin, LSBFIRST, 0b00110000);\n  digitalWrite(latchPin, HIGH);\n  digitalWrite(enablePin, LOW);\n}\n\nvoid Display (int Num, int wait) {\n  for (int d = 0; d &lt; sizeof(Digits); d++) {\n    int N = int(Num \/ pow(10, d)) % 10;\n    digitalWrite(latchPin, LOW);\n    byte dataR = (dec7seg[N] &lt;&lt; 4) | Digits[d];\n    byte dataL = (dec7seg[N] &gt;&gt; 4) | 0b00110000;\n    shiftOut(dataPin, clockPin, LSBFIRST, dataR);\n    shiftOut(dataPin, clockPin, LSBFIRST, dataL);\n    digitalWrite(latchPin, HIGH);\n    delay(wait);\n  }\n}\n\nint readsw () {\n  for (int sw = 0; sw &lt; sizeof(buttons); sw++) {\n    digitalWrite(latchPin, LOW);\n    byte dataR = swMask &amp; buttons[sw];\n    byte dataL = (~swMask) &amp; buttons[sw];\n    shiftOut(dataPin, clockPin, LSBFIRST, dataR);\n    shiftOut(dataPin, clockPin, LSBFIRST, dataL);\n    digitalWrite(latchPin, HIGH);\n    if (digitalRead(swPin) == LOW) return sw;\n  }\n  return -1;\n}\n\nconst byte swLeds[] {\n  0b00000000,\n  LedsRYG_G,\n  LedsRYG_R,\n  LedsRYG_R | LedsRYG_G,\n  LedsRYG_Y,\n  LedsRYG_Y | LedsRYG_G,\n  LedsRYG_Y | LedsRYG_R,\n  LedsRYG_Y | LedsRYG_R | LedsRYG_G,\n};\n\nvoid loop() {\n  int Num = millis() \/ 1000;\n\n\n  LedsRG = 0b00000000;\n  LedsRYG = 0b00000000;\n  int sw = readsw();\n  if (sw &gt;= 0) {\n    LedsRG = LedsRG_G4;\n    LedsRYG = swLeds[sw];\n  }\n  if (Num % 2) LedsRG = LedsRG | LedsRG_R1;\n  switch (sw) {\n    case 1:\n  if (sw == 1) wait += 10;\n      for (int i = 0; i &lt; 10; i++) {\n        Display(wait, 0);        \n        delay(20);\n      }\n      break;\n    case 2:\n  if (sw == 2 &amp;&amp; wait &gt; 0) wait -= 10;\n      for (int i = 0; i &lt; 10; i++) {\n        Display(wait, 0);        \n        delay(20);\n      }\n      break;\n    case 4:\n      Display(wait, 0);\n      break;\n    default:\n      Display(Num, wait);\n  }\n\n  digitalWrite(latchPin, LOW);\n  shiftOut(dataPin, clockPin, LSBFIRST, LedsRight);\n  shiftOut(dataPin, clockPin, LSBFIRST, LedsRYG);\n  digitalWrite(latchPin, HIGH);\n\n  digitalWrite(latchPin, LOW);\n  shiftOut(dataPin, clockPin, LSBFIRST, LedsRight);\n  shiftOut(dataPin, clockPin, LSBFIRST, LedsRG);\n  digitalWrite(latchPin, HIGH);\n}<\/pre>\n\n\n\n

Lo \u00fanico que no estar\u00eda en un c\u00f3digo de producci\u00f3n ser\u00eda la variable wait<\/em> de la funci\u00f3n Display<\/em>, que quedar\u00eda as\u00ed:<\/p>\n\n\n\n

void Display (int Num) {\n  for (int d = 0; d &lt; sizeof(Digits); d++) {\n    int N = int(Num \/ pow(10, d)) % 10;\n    digitalWrite(latchPin, LOW);\n    byte dataR = (dec7seg[N] &lt;&lt; 4) | Digits[d];\n    byte dataL = (dec7seg[N] &gt;&gt; 4) | 0b00110000;\n    shiftOut(dataPin, clockPin, LSBFIRST, dataR);\n    shiftOut(dataPin, clockPin, LSBFIRST, dataL);\n    digitalWrite(latchPin, HIGH);\n  }\n}<\/pre>\n\n\n\n

\u00bfPor qu\u00e9 introducir una pausa variable entre el refresco de cada d\u00eddito?, pues simplemente como demostraci\u00f3n de que s\u00f3lo uno de los cuatro d\u00edgitos est\u00e1 encendido al mismo tiempo. Vamos, por aumentar el elemento did\u00e1ctico, que a fin de cuentas esa es la excusa con la que me he comprado los juguetes...<\/p>\n","_es_post_name":"frontal-de-descodificador","_es_post_excerpt":"","_es_post_title":"Frontal de descodificador","_en_post_content":"","_en_post_name":"","_en_post_excerpt":"","_en_post_title":"","edit_language":"en","footnotes":""},"categories":[19,30],"tags":[20,31],"ninja_gutenberg_blocks_featured_media_urls":{"thumbnail":["https:\/\/lab.fawno.com\/wp-content\/uploads\/2016\/03\/PanelPCB_Front-150x150.png",150,150,true],"ninja_gutenberg_blocks_landscape_large":["https:\/\/lab.fawno.com\/wp-content\/uploads\/2016\/03\/PanelPCB_Front.png",1200,322,false],"ninja_gutenberg_blocks_portrait_large":["https:\/\/lab.fawno.com\/wp-content\/uploads\/2016\/03\/PanelPCB_Front.png",1200,322,false],"ninja_gutenberg_blocks_square_large":["https:\/\/lab.fawno.com\/wp-content\/uploads\/2016\/03\/PanelPCB_Front.png",1200,322,false],"ninja_gutenberg_blocks_landscape":["https:\/\/lab.fawno.com\/wp-content\/uploads\/2016\/03\/PanelPCB_Front.png",600,161,false],"ninja_gutenberg_blocks_portrait":["https:\/\/lab.fawno.com\/wp-content\/uploads\/2016\/03\/PanelPCB_Front.png",600,161,false],"ninja_gutenberg_blocks_square":["https:\/\/lab.fawno.com\/wp-content\/uploads\/2016\/03\/PanelPCB_Front.png",600,161,false],"full":["https:\/\/lab.fawno.com\/wp-content\/uploads\/2016\/03\/PanelPCB_Front.png",1642,441,false]},"_links":{"self":[{"href":"https:\/\/lab.fawno.com\/en\/wp-json\/wp\/v2\/posts\/170"}],"collection":[{"href":"https:\/\/lab.fawno.com\/en\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/lab.fawno.com\/en\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/lab.fawno.com\/en\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/lab.fawno.com\/en\/wp-json\/wp\/v2\/comments?post=170"}],"version-history":[{"count":16,"href":"https:\/\/lab.fawno.com\/en\/wp-json\/wp\/v2\/posts\/170\/revisions"}],"predecessor-version":[{"id":1860,"href":"https:\/\/lab.fawno.com\/en\/wp-json\/wp\/v2\/posts\/170\/revisions\/1860"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/lab.fawno.com\/en\/wp-json\/wp\/v2\/media\/144"}],"wp:attachment":[{"href":"https:\/\/lab.fawno.com\/en\/wp-json\/wp\/v2\/media?parent=170"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/lab.fawno.com\/en\/wp-json\/wp\/v2\/categories?post=170"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/lab.fawno.com\/en\/wp-json\/wp\/v2\/tags?post=170"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}