ท่านผู้รู้ช่วยดูโค้ด arduino เกี่ยวกับเครื่องชั่งน้ำหนักให้ด้วยครับ เพิ่งหัดทำ งงมากมาย

ช่วยแนะนำด้วยรับ ผมลองเขียนโปรแกรมเครื่องชั่งน้ำหนัก แบบลอก และตัดโค้ดมาผสมกัน
ผมทำได้แค่พื้นฐานคือให้ชั่ง และแสดงตัวเลขนำ้หนัก รวมทั้งใช้คีย์เพดพิมพ์ตัวเลขได้แค่นั้น
แต่ยังไม่ได้เป้าแบบที่อยากได้ครับ และตอนนี้ไปไม่เป็นแล้วครับ งงเกินจะบรรยายออกมาเป็นภาษาคน

เป้าหมายของเครื่องชั่งน้ำหนัก คือ

1.เปิดเครื่องแล้ว เครื่องสามารถชั่งน้ำหนักได้ปกติ โชว์ทศนิยม 2ตำแหน่ง  ... อันนี้ทำมั่วๆได้แล้วครับ
2.เมื่อกดคีย์เพด สามารถใส่ตัวเลขค่าใดๆ และจะเห็นที่จอ LCD (คนละแถวกับเลขที่ชั่งน้ำหนักในข้อ1) ...ข้อนี้สามารถกรอกตัวเลขขึ้นจอได้แล้วครับ
3.เมื่อกด enter ให้เอาเลขน้ำหนักที่ชั่งได้ มาลบกับเลขที่เราคีย์เข้าไปแล้วให้แสดงผลไปอีกที่บนหน้าจออีกจุดหนึ่ง
และถ้าเรายังชั่งน้ำหนักอยู่ตัวเลขในข้อ3จะเปลี่ยนแปลงไปเรื่อยๆ ก็คือลบกันแล้วแสดงตัวเลขหลังลบไปเรื่อยๆครับ .... อันนี้งงครับ ไม่รู้ต้องใช้ตัวแปรอะไรยังไงเพื่อให้มันเอาค่า เอามาลบกันแล้วแสดงออกมาตลอดเวลาครับ

รบกวนท่านผู้รู้แนะนำด้วยครับ
หรือมีใครรับเขียนโค้ดแบบดังกล่าวไหมครับ
ตอนนี้ผมไปไม่เป็นแล้ว

อันนี้โค้ดที่ผมทำไว้ครับ


#include <Wire.h>
#include <LiquidCrystal_I2C.h>
#include "Keypad.h"
#include <HX711.h>

LiquidCrystal_I2C lcd(0x3F, 16, 2); // Set the LCD address to 0x27 in PCF8574 by NXP and Set to 0x3F in PCF8574A by Ti
#define keyPad_Characters 16 // keyPad_Characters 16
const byte ROWS = 4; //four rows
const byte COLS = 4; //four columns
char keys[ROWS][COLS] =
{
  {'1', '2', '3', 'A'},
  {'4', '5', '6', 'B'},
  {'7', '8', '9', 'C'},
  {'*', '0', '.', 'D'}
};
byte rowPins[ROWS] = {9, 8, 7, 6}; //connect to the row pinouts of the keypad
byte colPins[COLS] = {5, 3, 4, 2}; //connect to the column pinouts of the keypad

char keyHistory[10]; //allows 15 key presses to be stored + the null char
byte num_count = 0; // Counts numbers in array
char key; // Key Presses
char Clear = 'C';
char Delete = 'D';
char Tare = 'B';
char Enter = 'A';
int grains = 0;
Keypad keypad = Keypad( makeKeymap(keys), rowPins, colPins, ROWS, COLS);
HX711 scale2(A1, A2); // parameter "gain" is ommited; the default value 128 is used by the library

#define MAXFLT 6 // 24 bit resolution is 7 digits
int button1 = 11;
int press1 = 0;

void setup()
{
    Serial.begin(115200);
  lcd.begin();
  lcd.setCursor(0, 0);
  lcd.print(" Weighting Scale ");
  lcd.setCursor(0, 1);
  lcd.print("--  C1  --");
  delay(3000);
  lcd.clear();

   scale2.set_scale(33002.f); // this value is obtained by calibrating the scale with known weights;
   scale2.tare(); // reset the scale to zero
  
  pinMode(button1, INPUT);
  digitalWrite(button1, HIGH); //enable pullups to make pin high
}

void clearData() // Clears char array ...
{
  while (num_count != 0)
  { // This can be used for any array size,
    keyHistory[num_count--] = 0; //clear array for new data
  }
  return;
}

void loop()
{
  key = keypad.getKey();
  if (key)
  {
    keyHistory[num_count] = key;      // store char into data array
    lcd.setCursor(num_count, 0);      // move cursor to show each new char stored into data array
    lcd.print(keyHistory[num_count]); // print char at said cursor
    Serial.println(keyHistory[num_count]);
    num_count++; // increment data array by 1 to store new char, also keep track of the number of chars entered
  }

    if (key == Tare)    // Tares Scale to zero, clears lcd, clears array ,กด B = Tare ล้างค่าน้ำหนักที่คีย์ใส่ และค่าน้ำหนักที่ชั่ง ให้เป็น 0
  {
    lcd.clear();
    lcd.setCursor(0, 1);
    lcd.print("<TARE>");
    delay(500);
    clearData();
    scale2.tare();
    lcd.clear();
  }
  
  if (key == Clear)   // Clears LCD, blinks backlight ,กด C = Clear ล้างค่าน้ำหนักที่คีย์ใส่ ให้เป็น 0 แต่ค่าน้ำหนักที่ชั่งจะยังคงอยู่ไม่เปลี่ยนไป
  {
    lcd.clear();
    lcd.print("<CLEAR>");
    delay(500);
    lcd.clear();
    clearData();
    lcd.setCursor(8, 1);
  }

  /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

  /*ตรงนี้งงว่า จะกำหนดให้มันมาลบกันได้ยังถ้ากด Enter ครับ
    if (key == Enter)  // Starts powder measure routine
  {
    keyHistory[num_count] = 0;  // Allows use of decimals in array
    grains = atof(keyHistory);
    // !!??  จะต้องแก้pยังไงให้เป็นว่า  ถ้าทำการกด enter (ปุ่มกดที่คีย์เพด "A" )ให้ทำการประมวลผลตัวเลข โดยเอาค่าน้ำหนักที่ได้ ไปลบ กับตัวเลขที่คีย์ลงไว้ แล้วแสดงผลตัวเลขออกมาที่จอ ตัวที่10 แถวที่2 ???? โค้ดด้านล่างผมทำแบบไม่เข้าใจ ซึ่งน่าจะผิดหลัก มันต้องทำตัวแปรแบบไหน ให้มันลบกันแล้วแสดงผลซำ้ๆวนตลอดเวลาที่เปิดเครื่อง หรือจนกว่าจะล้างข้อมูลที่คีย์ไว้ครับ.....
     scale2.get_units()-keyHistory[num_count];
    lcd.setCursor(10, 1);
    lcd.print(scale2.get_units(2)-keyHistory[num_count]);
  }
*/
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  float r;
  char buf[MAXFLT + 1];
  r = scale2.get_units(5); // average readings
  Serial.println(dtostrf(r, MAXFLT, 4, buf));
  lcd.setCursor(0, 1);
  lcd.print(dtostrf(r, MAXFLT, 2, buf)); // average readings
  {
    press1 = digitalRead(button1);
    if (press1 == LOW)
    {
      scale2.tare();
    }
    else {
      /// do nothing
   }
  }
  
  //การแสดงผลคำต่างๆที่จอlcd
  lcd.setCursor(10, 0);
  lcd.print("<WT.in");
  lcd.setCursor(6, 1);
  lcd.print("kg>");
  lcd.setCursor(14, 1);
  lcd.print("kg");
  
}
คำตอบที่ได้รับเลือกจากเจ้าของกระทู้
ความคิดเห็นที่ 1
เท่าที่ดูโปรแกรมก็ใกล้เคียงแล้วครับ ตรงส่วนที่ให้วนรอบเรื่อยๆ ก็เช็คง่ายๆว่า
1. key == Enter แล้ว
2. วนลูป while ด้วยเงื่อนไขคือสร้างตัวแปรตัวนึงมันเก็บเป็น flag ไว้ ถ้าตัวนี้เป็น 1 ให้หยุดวน
3. ในลูป ให้รับค่าจากตาชั่งมา แล้วเปรียบเทียบกับค่าที่เก็บไว้ (ทำถูกแล้วครับ แต่ตรง scale2.get_units()-keyHistory[num_count]; มีจุดผิดคือ 4. เอาค่าที่วัดจากตาชั่งมาลบกับ keyHistory[num_count] ที่เป็น string ไม่ได้ ต้องลบกับ grains ที่จขกท. แปลงเป็น double แล้วครับ 2. ตัวแปร grains ต้องประกาศเป็น double ไม่ใช่ int ครับ เพราะจขกท. จะรับค่าที่เป็นจำนวนจริง 3. คำสั่ง get_units() ถ้าใส่ตัวเลขเข้าไปในวงเล็บมันจะวัดค่าเป็นจำนวนครั้งเท่าตัวเลขแล้ว average ออกมานะครับ เผื่อได้ใช้ 4. ควรตั้งตัวแปรมาเก็บค่าที่ลบไว้เผื่อส่งออก serial และ print ครับ)
5. ส่งค่าจากข้อ 4 ออกจอ และ serial
6. เช็คปุ่มกดอีกรอบ ถ้าเป็นปุ่ม clear โดนกด ให้เปลี่ยนค่าตัวแปร flag ในข้อ 2 เป็น 1 โปรแกรมจะได้ออกจากลูปได้
7. รอสักพักก่อนแล้วค่อยวนลูปใหม่เพื่อให้อ่านค่าบนจอได้ อาจจะเอาตัวอย่าง Blink without delay มาดูช่วยนะครับ

จากนั้น การเคลียร์ค่า ให้แก้เงื่อนไขของกรณีกดปุ่ม Clear ให้รวมกรณีที่ flag ถูกตั้งเป็น 1 ไว้ด้วย เพื่อที่ว่าหลังกดปุ่ม Clear ให้ออกลูปแล้ว มันจะได้กลับมาทำงานต่อได้ (ปล. อย่าลืมปรับค่า flag กลับเป็นเหมือนเดิมด้วยนะครับ)

ส่วนที่แนะนำเพิ่มเติมคือ ในเงื่อนไข if(key) อาจจะต้องระบุไปเลยว่าให้นับเฉพาะการกดในช่วงปุ่มตัวเลขเท่านั้น ไม่อย่างนั้นมันจะนับรวมปุ่ม function ไปหมด

แล้วก็ ผมไม่แน่ใจว่าข้างล่างที่ต่อมาหลังเช็คปุ่มเอาไว้ทำอะไรนะครับ แต่แนะนำว่า อย่าประกาศตัวแปรกระจายทั่วโค้ดจะดีกว่านะครับ เอาไว้บนสุดหมดดีกว่า ส่วนการแสดงผลออกจอ ถ้าสร้าง function แยกไว้เลยสำหรับการแสดงผลแล้วค่อยใช้โค้ดหลักเรียก โค้ดจะสะอาดกว่าครับ

ตรง   pinMode(button1, INPUT);
  digitalWrite(button1, HIGH); //enable pullups to make pin high

แก้เป็น pinMode(button1,INPUT_PULLUP); เลยคำสั่งเดียวก็ได้ครับ สะดวกกว่า
https://www.arduino.cc/reference/en/language/functions/digital-io/pinmode/

สงสัยอะไรถามได้ครับ
แสดงความคิดเห็น
โปรดศึกษาและยอมรับนโยบายข้อมูลส่วนบุคคลก่อนเริ่มใช้งาน อ่านเพิ่มเติมได้ที่นี่