Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

How to read pwm (led eg) in loop() ? #33

Closed
wahidsa opened this issue Jun 25, 2020 · 5 comments
Closed

How to read pwm (led eg) in loop() ? #33

wahidsa opened this issue Jun 25, 2020 · 5 comments

Comments

@wahidsa
Copy link

wahidsa commented Jun 25, 2020

Hello,
I am noob kind-of, I uploaded the LED sketch example and it works fine, but i need to do stuff in loop() for the value of pwm written or given through the Home app.
I wanted to run infrared signal "code" through an IRLed, when i set led pwm to 20, will send code 20 "IRSend library" to air-conditioner.
the issue is I cant get to read the pwm in loop (main tab called led) , neither can use the library or send the code in (my_accessory.h tab)
I tried Serial.println(led_bri.value.int_value); but always gives me same value 6510
I was able to get the ON/OFF state, but not the pwm value.
I know im missing something
i tried many things but all lead to fail.
thank you for your time.

@Mixiaoxiao
Copy link
Owner

Paste your code here.

@wahidsa
Copy link
Author

wahidsa commented Jun 25, 2020

the my_accessory.c

`/*

  • my_accessory.c
  • Define the accessory in C language using the Macro in characteristics.h
  • Created on: 2020-05-15
  •  Author: Mixiaoxiao (Wang Bin)
    

*/

#include <Arduino.h>
#include <homekit/homekit.h>
#include <homekit/characteristics.h>

#define PIN_LED 2

int led_bri = 100; //[0, 100]
bool led_power = false; //true or flase

homekit_value_t led_on_get() {
return HOMEKIT_BOOL(led_power);
}

void led_on_set(homekit_value_t value) {
if (value.format != homekit_format_bool) {
printf("Invalid on-value format: %d\n", value.format);
return;
}
led_power = value.bool_value;
if (led_power) {
if (led_bri < 1) {
led_bri = 100;
}
}
led_update();
}

homekit_value_t light_bri_get() {
return HOMEKIT_INT(led_bri);
}

void led_bri_set(homekit_value_t value) {
if (value.format != homekit_format_int) {
return;
}
led_bri = value.int_value;
led_update();
}

void my_accessory_identify(homekit_value_t _value) {
printf("accessory identify\n");
}

// Switch (HAP section 8.38)
// required: ON
// optional: NAME

// format: bool; HAP section 9.70; write the .setter function to get the switch-event sent from iOS Home APP.
homekit_characteristic_t led_on = HOMEKIT_CHARACTERISTIC_(ON, false,
//.callback=HOMEKIT_CHARACTERISTIC_CALLBACK(switch_on_callback),
.getter = led_on_get,
.setter = led_on_set
);

// format: string; HAP section 9.62; max length 64
homekit_characteristic_t cha_name = HOMEKIT_CHARACTERISTIC_(NAME, "Temperature");

homekit_accessory_t accessories[] = {
HOMEKIT_ACCESSORY(.id=1,
.category=homekit_accessory_category_lightbulb,
.services=(homekit_service_t
[]) {
HOMEKIT_SERVICE(ACCESSORY_INFORMATION, .characteristics=(homekit_characteristic_t*[]) {
HOMEKIT_CHARACTERISTIC(NAME, "Temperature"),
HOMEKIT_CHARACTERISTIC(MANUFACTURER, "Wahid"),
HOMEKIT_CHARACTERISTIC(SERIAL_NUMBER, "0000457"),
HOMEKIT_CHARACTERISTIC(MODEL, "AirCondition"),
HOMEKIT_CHARACTERISTIC(FIRMWARE_REVISION, "1.0"),
HOMEKIT_CHARACTERISTIC(IDENTIFY, my_accessory_identify),
NULL
}),
HOMEKIT_SERVICE(LIGHTBULB, .primary=true,
.characteristics=(homekit_characteristic_t*[]){
HOMEKIT_CHARACTERISTIC(NAME, "Led"),
&led_on,
// &cha_name,
HOMEKIT_CHARACTERISTIC(BRIGHTNESS, 100,
.getter=light_bri_get,
.setter=led_bri_set
),
NULL
}),
NULL
}),
NULL
};

void led_update() {
if (led_power) {
int pwm = PWMRANGE - (int) (led_bri * 1.0 * PWMRANGE / 100.0 + 0.5f);
analogWrite(PIN_LED, pwm);
printf("ON %3d (pwm: %4d of %d)\n", led_bri, pwm, PWMRANGE);
} else {
printf("OFF\n");
digitalWrite(PIN_LED, HIGH);
}
}

void occupancy_toggle() {

// const uint8_t state = occupancy_detected.value.uint8_value;
// occupancy_detected.value = HOMEKIT_UINT8((!state) ? 1 : 0);
// homekit_characteristic_notify(&occupancy_detected, occupancy_detected.value);
}

void led_toggle() {
led_on.value.bool_value = !led_on.value.bool_value;
led_on.setter(led_on.value);
homekit_characteristic_notify(&led_on, led_on.value);
}

homekit_server_config_t config = {
.accessories = accessories,
.password = "111-11-111"
};`

@wahidsa
Copy link
Author

wahidsa commented Jun 25, 2020

the main code "led.homekit.ino"

`#include <Arduino.h>
#include <arduino_homekit_server.h>
#include "ButtonDebounce.h"
#include "ButtonHandler.h"
/*#include <IRsend.h>
int irLed = 14; //D5 iR LED
IRsend irsend (irLed);

uint16_t OFF[171] = {6030, 1086, 1178, 436, 1178, 438, 460, 1148, 456, 1212, 458, 1148, 456, 1146, 1178, 440, 456, 1210, 456, 1150, 456, 1150, 458, 1148, 456, 1208, 1178, 436, 1202, 416, 458, 1146, 460, 1210, 458, 1148, 458, 1150, 456, 1150, 456, 1210, 456, 1144, 1176, 440, 460, 1150, 454, 1206, 1178, 438, 1204, 414, 456, 1150, 456, 1210, 456, 1148, 458, 1148, 458, 1146, 458, 1210, 456, 1152, 456, 1148, 456, 1148, 460, 1208, 456, 1144, 1206, 414, 458, 1148, 456, 1208, 1204, 414, 456, 1150, 456, 1150, 454, 1212, 456, 1150, 456, 1150, 456, 1146, 458, 1214, 452, 1150, 458, 1148, 456, 1150, 456, 1212, 458, 1144, 1174, 442, 458, 1148, 456, 1208, 1176, 442, 458, 1150, 454, 1152, 454, 1210, 458, 1148, 456, 1150, 456, 1148, 458, 1210, 456, 1150, 456, 1150, 456, 1150, 456, 1210, 458, 1144, 1174, 444, 456, 1152, 454, 1206, 1174, 444, 458, 1150, 454, 1152, 452, 1208, 1174, 444, 456, 1150, 458, 1144, 1200, 476, 1172, 442, 1202, 412, 1174, 440, 1200, 422, 1196}; // UNKNOWN AE963374
uint16_t cold20[171] = {5990, 1130, 372, 1234, 372, 1228, 1144, 470, 1146, 534, 374, 1232, 374, 1228, 1144, 474, 374, 1286, 1146, 470, 1146, 472, 374, 1230, 376, 1314, 1120, 468, 1146, 474, 374, 1232, 372, 1296, 372, 1232, 374, 1232, 374, 1234, 374, 1292, 374, 1226, 1148, 472, 374, 1230, 374, 1288, 1146, 468, 1146, 474, 374, 1232, 374, 1292, 376, 1256, 348, 1234, 372, 1232, 372, 1294, 374, 1232, 374, 1232, 372, 1234, 374, 1292, 372, 1228, 1144, 474, 374, 1234, 372, 1288, 1146, 474, 374, 1232, 374, 1234, 372, 1294, 372, 1232, 374, 1232, 374, 1230, 376, 1292, 374, 1232, 374, 1230, 376, 1230, 376, 1292, 376, 1228, 1146, 472, 374, 1232, 374, 1288, 1146, 472, 374, 1232, 374, 1232, 372, 1292, 376, 1230, 374, 1232, 374, 1234, 372, 1292, 374, 1232, 374, 1232, 372, 1230, 376, 1294, 372, 1228, 1146, 474, 374, 1256, 350, 1288, 1146, 474, 374, 1232, 372, 1232, 374, 1290, 1144, 474, 374, 1228, 1146, 472, 374, 1294, 374, 1256, 352, 1230, 374, 1234, 372, 1232, 1144}; // UNKNOWN 1621CDD4
uint16_t cold21[171] = {6042, 1080, 430, 1174, 430, 1174, 1160, 480, 1138, 542, 404, 1176, 430, 1172, 1164, 482, 404, 1236, 432, 1176, 430, 1174, 432, 1176, 430, 1232, 1164, 478, 1138, 480, 404, 1174, 430, 1234, 1164, 482, 402, 1174, 432, 1176, 432, 1236, 430, 1174, 1162, 482, 404, 1176, 430, 1232, 1166, 478, 1138, 482, 428, 1148, 432, 1236, 430, 1174, 432, 1174, 432, 1176, 430, 1236, 430, 1176, 428, 1176, 430, 1176, 430, 1238, 430, 1170, 1164, 484, 404, 1176, 430, 1234, 1164, 482, 402, 1176, 428, 1178, 428, 1238, 430, 1176, 430, 1174, 430, 1178, 430, 1236, 430, 1176, 430, 1174, 430, 1172, 434, 1236, 430, 1172, 1166, 480, 428, 1152, 428, 1232, 1192, 456, 430, 1148, 454, 1150, 432, 1238, 430, 1174, 456, 1150, 430, 1176, 454, 1210, 434, 1178, 452, 1150, 454, 1150, 454, 1212, 456, 1148, 1194, 450, 430, 1148, 456, 1206, 1196, 450, 458, 1122, 482, 1122, 456, 1204, 1198, 446, 1170, 450, 458, 1122, 484, 1182, 484, 1122, 486, 1120, 486, 1122, 482, 1124, 1194}; // UNKNOWN 191BEFEC
uint16_t cold22[171] = {5984, 1136, 428, 1176, 430, 1172, 1162, 456, 1158, 548, 402, 1178, 430, 1170, 1134, 488, 428, 1238, 430, 1176, 428, 1178, 430, 1178, 426, 1236, 1134, 508, 1134, 486, 402, 1174, 430, 1238, 428, 1172, 1162, 462, 426, 1174, 432, 1240, 428, 1172, 1162, 484, 402, 1176, 428, 1236, 1158, 458, 1130, 514, 402, 1178, 428, 1236, 430, 1178, 428, 1176, 430, 1176, 430, 1240, 428, 1176, 430, 1178, 428, 1176, 430, 1238, 430, 1174, 1158, 462, 428, 1176, 430, 1234, 1160, 460, 428, 1178, 428, 1176, 428, 1240, 428, 1180, 428, 1174, 430, 1176, 430, 1238, 430, 1178, 428, 1178, 430, 1176, 428, 1238, 430, 1172, 1136, 512, 402, 1178, 428, 1234, 1136, 508, 402, 1176, 430, 1176, 430, 1234, 1164, 458, 426, 1178, 428, 1178, 428, 1240, 428, 1178, 428, 1178, 428, 1178, 428, 1238, 430, 1172, 1168, 478, 402, 1178, 428, 1232, 1166, 480, 402, 1178, 428, 1178, 454, 1214, 428, 1178, 454, 1148, 1164, 482, 426, 1210, 1140, 506, 428, 1152, 428, 1176, 456, 1150, 1166}; // UNKNOWN 483AC1E0
uint16_t cold23[171] = {6040, 1080, 430, 1174, 456, 1146, 1160, 480, 1136, 544, 404, 1176, 428, 1172, 1164, 480, 404, 1236, 430, 1178, 428, 1176, 430, 1176, 430, 1232, 1164, 478, 1140, 480, 428, 1150, 430, 1232, 1168, 476, 1140, 480, 430, 1150, 428, 1238, 430, 1172, 1162, 484, 406, 1174, 428, 1234, 1166, 476, 1168, 452, 430, 1150, 454, 1212, 430, 1176, 430, 1174, 432, 1176, 430, 1236, 430, 1178, 428, 1178, 430, 1176, 430, 1236, 430, 1174, 1190, 454, 430, 1148, 456, 1208, 1164, 480, 430, 1148, 454, 1150, 430, 1236, 432, 1176, 454, 1150, 456, 1150, 456, 1212, 452, 1154, 456, 1152, 454, 1150, 456, 1212, 456, 1146, 1194, 452, 456, 1122, 458, 1204, 1196, 450, 458, 1120, 484, 1122, 458, 1210, 482, 1124, 456, 1150, 456, 1148, 458, 1210, 458, 1148, 456, 1150, 456, 1148, 458, 1208, 484, 1118, 1194, 452, 460, 1120, 484, 1176, 1194, 452, 458, 1122, 484, 1120, 486, 1178, 1196, 450, 458, 1116, 1194, 452, 458, 1182, 484, 1120, 486, 1118, 486, 1122, 484, 1120, 1196}; // UNKNOWN F6C406D4
uint16_t cold24[171] = {6040, 1080, 484, 1120, 486, 1114, 1196, 446, 1168, 514, 458, 1120, 486, 1116, 1194, 452, 458, 1182, 486, 1120, 486, 1120, 486, 1120, 486, 1176, 1194, 448, 1168, 452, 460, 1118, 486, 1182, 484, 1120, 486, 1118, 1192, 452, 460, 1180, 486, 1116, 1192, 452, 460, 1120, 486, 1176, 1194, 448, 1166, 454, 458, 1120, 486, 1182, 486, 1120, 486, 1122, 484, 1120, 486, 1182, 484, 1120, 486, 1122, 484, 1120, 486, 1180, 486, 1118, 1192, 452, 458, 1118, 488, 1174, 1196, 452, 460, 1118, 486, 1120, 486, 1180, 488, 1120, 486, 1120, 486, 1120, 486, 1182, 486, 1118, 486, 1120, 486, 1120, 486, 1180, 484, 1116, 1192, 454, 458, 1120, 484, 1178, 1192, 454, 458, 1120, 486, 1120, 486, 1182, 486, 1118, 488, 1122, 484, 1120, 486, 1182, 486, 1122, 484, 1120, 486, 1122, 484, 1184, 484, 1116, 1192, 454, 456, 1124, 484, 1178, 1192, 454, 456, 1124, 482, 1122, 484, 1182, 486, 1118, 1192, 450, 1164, 456, 454, 1186, 484, 1122, 484, 1122, 484, 1122, 484, 1124, 1190}; // UNKNOWN 85B2983C
uint16_t cold25[171] = {6042, 1078, 430, 1176, 428, 1174, 1162, 478, 1168, 512, 430, 1152, 428, 1172, 1164, 480, 430, 1210, 430, 1176, 430, 1178, 428, 1176, 430, 1232, 1162, 480, 1140, 480, 428, 1150, 430, 1232, 1164, 484, 402, 1174, 1136, 506, 404, 1238, 428, 1172, 1164, 482, 402, 1176, 430, 1234, 1166, 476, 1136, 484, 404, 1176, 430, 1238, 428, 1176, 430, 1176, 430, 1178, 428, 1238, 428, 1178, 428, 1176, 430, 1176, 430, 1238, 428, 1170, 1164, 484, 402, 1174, 432, 1234, 1164, 482, 402, 1178, 428, 1176, 430, 1238, 428, 1180, 428, 1176, 432, 1174, 430, 1238, 430, 1174, 432, 1176, 428, 1178, 428, 1234, 432, 1172, 1164, 482, 430, 1148, 430, 1232, 1166, 480, 430, 1148, 430, 1174, 456, 1212, 430, 1178, 428, 1176, 456, 1150, 454, 1216, 454, 1150, 430, 1174, 454, 1152, 456, 1212, 456, 1146, 1194, 452, 440, 1138, 458, 1206, 1192, 452, 458, 1122, 456, 1150, 456, 1208, 1194, 446, 1168, 446, 1168, 450, 458, 1182, 484, 1124, 456, 1150, 458, 1148, 482, 1124, 1194}; // UNKNOWN 7F08A680
uint16_t hot23[171] = {6038, 1082, 484, 1122, 484, 1116, 1192, 448, 1164, 510, 1166, 450, 1164, 454, 458, 1120, 486, 1182, 486, 1120, 486, 1118, 488, 1118, 486, 1180, 1192, 448, 1166, 452, 458, 1120, 486, 1176, 1194, 448, 1168, 452, 458, 1120, 488, 1180, 486, 1116, 1192, 452, 460, 1118, 486, 1176, 1196, 446, 1168, 452, 458, 1120, 486, 1180, 486, 1122, 484, 1120, 488, 1118, 486, 1180, 488, 1120, 488, 1118, 486, 1118, 488, 1182, 482, 1118, 1196, 450, 460, 1118, 486, 1178, 1198, 450, 460, 1120, 484, 1120, 484, 1182, 484, 1124, 484, 1122, 484, 1122, 484, 1182, 486, 1120, 484, 1122, 486, 1120, 486, 1182, 484, 1116, 1196, 452, 458, 1118, 488, 1178, 1194, 450, 460, 1120, 484, 1120, 486, 1178, 1194, 452, 458, 1120, 484, 1120, 484, 1182, 486, 1118, 486, 1120, 486, 1120, 484, 1184, 486, 1114, 1194, 452, 460, 1118, 484, 1178, 1192, 452, 458, 1122, 484, 1118, 486, 1176, 1196, 452, 458, 1116, 1194, 452, 458, 1184, 484, 1120, 486, 1120, 486, 1120, 484, 1124, 1192}; // UNKNOWN E2A64114
uint16_t hot25[171] = {6038, 1082, 484, 1120, 486, 1116, 1194, 450, 1164, 512, 1164, 450, 1166, 454, 458, 1120, 486, 1182, 484, 1120, 484, 1122, 486, 1118, 488, 1176, 1194, 450, 1164, 454, 460, 1120, 484, 1176, 1194, 454, 458, 1116, 1192, 454, 460, 1180, 486, 1116, 1194, 452, 458, 1120, 486, 1178, 1190, 450, 1164, 454, 460, 1118, 488, 1180, 488, 1118, 488, 1118, 486, 1120, 488, 1180, 486, 1118, 488, 1120, 486, 1118, 488, 1180, 486, 1114, 1194, 452, 458, 1120, 486, 1176, 1194, 454, 458, 1120, 486, 1120, 484, 1184, 484, 1120, 486, 1120, 484, 1122, 486, 1180, 486, 1120, 484, 1122, 484, 1118, 486, 1182, 486, 1114, 1192, 454, 458, 1120, 484, 1178, 1192, 454, 456, 1120, 484, 1122, 486, 1180, 484, 1122, 484, 1118, 488, 1122, 484, 1182, 484, 1124, 482, 1122, 486, 1120, 484, 1184, 482, 1118, 1190, 456, 452, 1126, 484, 1180, 1192, 454, 452, 1128, 482, 1122, 484, 1178, 1190, 454, 1160, 454, 1154, 466, 452, 1184, 1186, 454, 1156, 458, 1158, 456, 1156, 462, 1160}; // UNKNOWN 6C4EF873
int type; //hot/cold
*/
//#include "wifi_info.h"
#include "WiFiManager.h"
WiFiManager manager;

#define LOG_D(fmt, ...) printf_P(PSTR(fmt "\n") , ##VA_ARGS);

// access your HomeKit characteristics defined in my_accessory.c
extern "C" homekit_server_config_t config;
extern "C" homekit_characteristic_t led_bri;
extern "C" void occupancy_toggle();
extern "C" void led_toggle();
extern "C" void accessory_init();

#define PIN_SWITCH 2 //Relay pin
#define SwitchInit true // initial state
#define RelayTime 200 // ms till return to initial state, zero to ignore
long start=millis();

void blink_led(int interval, int count) {
for (int i = 0; i < count; i++) {
builtinledSetStatus(true);
delay(interval);
builtinledSetStatus(false);
delay(interval);
}
}
//void pp(int i){
// Serial.println(i);
//}

void setup() {
Serial.begin(115200);

// pinMode (irLed, OUTPUT);
manager.autoConnect("HOMEKIT");
// wifi_connect(); // in wifi_info.h
my_homekit_setup();
}

void loop() {
my_homekit_loop();
delay(10);
if (millis()-start>5000) {
start=millis();Serial.println(led_bri.value.int_value);
}
if (!digitalRead(0)) { //reset all settings
digitalWrite(2, LOW);
delay(2000);
if (!digitalRead(0)) {
homekit_storage_reset();
// manager.resetSettings();
ESP.reset();
}
digitalWrite(2, HIGH);
}

}

void builtinledSetStatus(bool on) {
digitalWrite(PIN_SWITCH, on ? LOW : HIGH);
}

//==============================
// HomeKit setup and loop
//==============================

ButtonDebounce btn(0, INPUT_PULLUP, LOW);
ButtonHandler btnHandler;

void IRAM_ATTR btnInterrupt() {
btn.update();
}

static uint32_t next_heap_millis = 0;

//Called when the switch value is changed by iOS Home APP
void led_on_setter(homekit_value_t value) {
/* bool on = value.bool_value;
led_on.value.bool_value = on; //sync the value
LOG_D("Switch: %s", on ? "ON" : "OFF");
// digitalWrite(PIN_SWITCH, on ? LOW : HIGH);
// if (RelayTime) {
// delay(RelayTime);
// digitalWrite(PIN_SWITCH, SwitchInit);
// }*/
//int led_br = value.int_value;
led_bri.value.int_value = value.int_value;

// int pwm = PWMRANGE - (int) (led_bri * 1.0 * PWMRANGE / 100.0 + 0.5f);
//Serial.println(pwm);
Serial.println(int(led_bri.value.int_value));
}

void my_homekit_setup() {
// digitalWrite(PIN_SWITCH, SwitchInit);
// pinMode(PIN_SWITCH, OUTPUT);

//Add the .setter function to get the switch-event sent from iOS Home APP.
//The .setter should be added before arduino_homekit_setup.
//HomeKit sever uses the .setter_ex internally, see homekit_accessories_init function.
//Maybe this is a legacy design issue in the original esp-homekit library,
//and I have no reason to modify this "feature".

// led_bri.setter = led_on_setter;
arduino_homekit_setup(&config);

//report the switch value to HomeKit if it is changed (e.g. by a physical button)
// bool switch_is_on = true/false;
// cha_switch_on.value.bool_value = switch_is_on;
// homekit_characteristic_notify(&cha_switch_on, cha_switch_on.value);
btn.setCallback(std::bind(&ButtonHandler::handleChange, &btnHandler,
std::placeholders::_1));
btn.setInterrupt(btnInterrupt);
btnHandler.setIsDownFunction(std::bind(&ButtonDebounce::checkIsDown, &btn));
btnHandler.setCallback([](button_event e) {
if (e == BUTTON_EVENT_SINGLECLICK) {
LOG_D("Button Event: SINGLECLICK");
led_toggle();
} else if (e == BUTTON_EVENT_DOUBLECLICK) {
LOG_D("Button Event: DOUBLECLICK");
occupancy_toggle();
} else if (e == BUTTON_EVENT_LONGCLICK) {
LOG_D("Button Event: LONGCLICK");
LOG_D("Rebooting...");
// homekit_storage_reset();
// ESP.restart(); // or system_restart();
}
});
}

void my_homekit_loop() {
arduino_homekit_loop();
const uint32_t t = millis();
if (t > next_heap_millis) {
// show heap info every 5 seconds
next_heap_millis = t + 5 * 1000;
LOG_D("Free heap: %d, HomeKit clients: %d",
ESP.getFreeHeap(), arduino_homekit_connected_clients_count());

}
}`

@Mixiaoxiao
Copy link
Owner

Read the Example01~04 to understand the full logic.
This is not an issue about this project, but a question about how to code.

Your characteristic BRIGHTNESS has its .setter and .getter, and you sync the brightness-value to var led_bri in function led_bri_set and your value in characteristic BRIGHTNESS is not synced. Two ways:

  • The brightness-value is var led_bri, write extern "C" int led_bri; and you can access the var led_bri in your ino.
  • Define your characteristic BRIGHTNESS as a var named e.g. cha_brightness (like led_on, cha_name ), and sync its value in its .setter function by writing cha_brightness.value.int_value = value.int_value; (See Example02_Switch)

BTW, the .setter and .getter functions logic is as follows:

  • When HomeKit changed the cha value:
    if cha has .setter then call its .setter function;
    else just change(sync to) cha's value.
  • When HomeKit need read the cha value: (e.g. sync value when reconnected)
    if cha has .getter then return the .getter function value (does not read its value);
    else just return its value.

I do think the design (by author maximkulkin) of .setter and .getter is not easy for coding beginners to understand, but it is a really good design to "hook" the cha changing and reading event. Also, there is a .callback can do this thing but it will give the coding beginners a more complex thing to understand.

@wahidsa
Copy link
Author

wahidsa commented Jun 27, 2020

thank you so much for your help in my code.
i tried the first one>>> WORKED GREAT
GREAT WORK YOU DID

I even upgraded my skills to include many accessories :)

@wahidsa wahidsa closed this as completed Jun 27, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants