Vôn kế bí mật trong Arduino - đo điện áp pin bằng vi điều khiển Vôn kế kỹ thuật số trên Arduino có kết nối với PC qua cổng nối tiếp

Ý tưởng

Ý tưởng các thiết bị đo điện áp, dòng điện, công suất, dòng điện và có thể cả điện tích đã ra đời từ lâu và không chỉ đối với tôi. Bạn có thể tìm thấy nhiều đồ chơi có tên USB Bút thử (Bác sĩ) để thử nghiệm nhiều thiết bị khác nhau từ USB. Tôi quan tâm hơn một chút thiết bị đa năng, độc lập với giao diện, nhưng được thiết kế đơn giản cho các điện áp và dòng điện nhất định. Ví dụ: 0 - 20,00v, 0 - 5,00a, 0 - 99,99Ah. Về chức năng thì mình thấy thế này

  • Hiển thị điện áp và dòng điện hiện tại, nghĩa là đồng hồ đo volt-ampe. Về nguyên tắc, bạn có thể phản ánh ngay sức mạnh.
  • Đếm và hiển thị dung lượng tích lũy. Tính theo giờ ampe và rất có thể tính theo giờ watt.
  • Hiển thị thời gian xử lý
  • Và rất có thể, ngưỡng cắt điện áp trên và dưới có thể điều chỉnh được (giới hạn phóng điện và sạc)

Phát triển

Để thực hiện các phép tính và đo lường, chúng ta cần một bộ điều khiển. Tôi nhớ đến ý tưởng này khi làm quen với Arduino, vì vậy bộ điều khiển sẽ là một chiếc Atmega328 phổ biến đơn giản và nó sẽ được lập trình trong môi trường Arduino. Từ quan điểm kỹ thuật, sự lựa chọn có lẽ không phải là tốt nhất - bộ điều khiển hơi phức tạp đối với nhiệm vụ và ADC của nó không thể được gọi là đo lường, nhưng... chúng tôi sẽ thử.

  • Chúng tôi sẽ không hàn nhiều trong dự án này. Để làm cơ sở, chúng tôi sẽ lấy một bản làm sẵn mô-đun Arduino Pro Mini, may mắn thay người Trung Quốc sẵn sàng cung cấp chúng với giá bán lẻ 1,5 USD.
  • Thiết bị hiển thị sẽ là màn hình 1602 - 1,5 USD khác. Tôi có một tùy chọn với mô-đun giao diện I2C, nhưng trong dự án này nó không thực sự cần thiết ($0,7).
  • Để phát triển chúng ta cần bảng bánh mì. Trong trường hợp của tôi, đây là một BreadBoard nhỏ với giá 1 đô la.
  • Tất nhiên, bạn sẽ cần dây và một số điện trở có giá trị khác nhau. Đối với màn hình 1602 không có I2C, bạn cũng cần chọn độ tương phản - việc này đã xong biến trởở mức 2 - 20 kOhm.
  • Để thực hiện một ampe kế, bạn sẽ cần một shunt. Theo ước tính đầu tiên, nó có thể là điện trở 0,1 Ohm, 5 W.
  • Để thực hiện tự động tắt máy, bạn sẽ cần một rơle có các tiếp điểm được thiết kế cho dòng điện tối đa của thiết bị và điện áp bằng điện áp nguồn. Để điều khiển rơle bạn cần bóng bán dẫn npn và một diode bảo vệ.
  • Thiết bị sẽ được cung cấp năng lượng bởi nguồn bên ngoài nguồn điện, rõ ràng, ít nhất là 5 V. Nếu nguồn điện thay đổi nhiều thì cũng cần có bộ ổn định tích hợp loại 7805 - nó sẽ xác định điện áp rơle.
  • Khi Arduino chuyên nghiệp Mini sẽ yêu cầu bộ chuyển đổi USB-TTL để tải chương trình cơ sở lên.
  • Để thiết lập, bạn sẽ cần một đồng hồ vạn năng.

Vôn kế

Tôi đang triển khai một vôn kế đơn giản với phạm vi khoảng 0 - 20V. Lưu ý này rất quan trọng vì ADC của bộ điều khiển của chúng tôi có dung lượng 10 bit (1024 giá trị riêng biệt), do đó sai số sẽ ít nhất là 0,02 V (20/1024). Để triển khai phần cứng, chúng ta cần một đầu vào tương tự của bộ điều khiển, một bộ chia được tạo thành từ một cặp điện trở và một số loại đầu ra (màn hình ở phiên bản hoàn thiện, có thể sử dụng cổng nối tiếp để gỡ lỗi).

Nguyên tắc phép đo ADC bao gồm việc so sánh điện áp ở đầu vào tương tự với VRef tham chiếu. Đầu ra ADC luôn là số nguyên - 0 tương ứng với 0V, 1023 tương ứng với điện áp VRef. Phép đo được thực hiện bằng cách lấy một loạt các giá trị điện áp liên tiếp và lấy trung bình trong khoảng thời gian giữa các lần cập nhật giá trị trên màn hình. Việc lựa chọn điện áp tham chiếu rất quan trọng vì nó mặc định là điện áp nguồn, có thể không ổn định. Điều này hoàn toàn không phù hợp với chúng tôi - chúng tôi sẽ lấy một nguồn tham chiếu nội bộ ổn định có điện áp 1,1V làm cơ sở, khởi tạo nó bằng cách gọi analogReference(INTERNAL). Sau đó chúng tôi sẽ hiệu chỉnh giá trị của nó bằng cách sử dụng số đo của đồng hồ vạn năng.

Sơ đồ bên trái hiển thị một biến thể có điều khiển trực tiếp màn hình (nó được điều khiển đơn giản - xem bản phác thảo LiquidCrystal\HelloWorld tiêu chuẩn). Bên phải là tùy chọn I2C mà tôi sẽ sử dụng thêm. I2C cho phép bạn tiết kiệm dây (trong đó phiên bản thông thường- 10, không tính đèn nền). Nhưng đồng thời cần thiết mô-đun bổ sung và khởi tạo phức tạp hơn. Trong mọi trường hợp, việc hiển thị các ký tự trên mô-đun trước tiên phải được kiểm tra và điều chỉnh độ tương phản - để thực hiện việc này, bạn chỉ cần hiển thị bất kỳ văn bản nào sau khi khởi tạo. Độ tương phản được điều chỉnh bằng điện trở R1 hoặc điện trở tương tự của mô-đun I2C.

Đầu vào là bộ chia 1:19, cho phép bạn nhận được điện áp tối đa khoảng 20V (thường là tụ điện + diode zener được đặt song song với đầu vào để bảo vệ, nhưng hiện tại điều này không quan trọng đối với chúng tôi). Các điện trở có độ chênh lệch và Vref tham chiếu của bộ điều khiển cũng vậy, vì vậy sau khi lắp ráp, chúng ta cần đo điện áp (ít nhất là nguồn cung cấp) song song với thiết bị của chúng ta và đồng hồ vạn năng tham chiếu và chọn Vref trong mã cho đến khi số đọc khớp. Cũng cần lưu ý rằng bất kỳ ADC nào cũng có điện áp bù bằng 0 (làm hỏng số đọc ở đầu phạm vi), nhưng bây giờ chúng ta sẽ không đi sâu vào vấn đề đó.

Điều quan trọng nữa là phải tách biệt nơi cung cấp và nơi đo lường. ADC của chúng tôi có độ phân giải kém hơn 1mV một chút, điều này có thể gây ra sự cố nếu nối dây không chính xác, đặc biệt là trên bảng mạch bánh mì. Vì việc bố trí bảng mô-đun đã được thực hiện xong và chúng ta chỉ còn việc chọn các chân cắm. Mô-đun này có một số chân “nối đất”, vì vậy chúng ta phải đảm bảo rằng nguồn điện đi vào mô-đun thông qua một “mặt đất” và các phép đo qua chân kia. Trên thực tế, để thực hiện các thay đổi, tôi luôn sử dụng chân nối đất gần đầu vào analog nhất.

Để điều khiển I2C, một phiên bản của thư viện LiquidCrystal_I2C được sử dụng - trong trường hợp của tôi, sơ đồ chân cụ thể của mô-đun I2C được chỉ định (các mô-đun sản xuất của Trung Quốc có các điều khiển khác nhau). Tôi cũng lưu ý rằng I2C trong Arduino liên quan đến việc sử dụng các chân A4, A5 - trên bảng chuyên nghiệp Mini, chúng không nằm ở rìa, điều này gây bất tiện cho việc tạo mẫu trên BreadBoard.

Nguồn

#bao gồm #bao gồm // Vôn kế đơn giản với màn hình i2c 1602. V 16.11 // Cài đặt cho màn hình i2c 1602 với sơ đồ chân không chuẩn #define LCD_I2C_ADDR 0x27 #define BACKLIGHT 3 #define LCD_EN 2 #define LCD_RW 1 #define LCD_RS 0 #define LCD_D4 4 #define LCD_D5 5 #define LCD_D6 6 #define LCD_D7 7 LiquidCrystal_I2C lcd(LCD_I2C_ADDR,LCD_EN,LCD_RW,LCD_RS,LCD_D4,LCD_D5,LCD_D6,LCD_D7); // Đọc thời gian cập nhật, ms (200-2000) #define REFRESH_TIME 330 // Đầu vào analog #define PIN_VOLT A0 // Điện áp tham chiếu bên trong (chọn) const float VRef = 1.10; // Hệ số chia điện trở đầu vào (Rh + Rl) / Rl. TRONG<-[ Rh ]--(analogInPin)--[ Rl ]--|GND const float VoltMult = (180.0 + 10.0) / 10.0; float InVolt, Volt; void setup() { analogReference(INTERNAL); // Инициализация дисплея lcd.begin (16, 2); lcd.setBacklightPin(BACKLIGHT, POSITIVE); lcd.setBacklight(HIGH); // включить подсветку lcd.clear(); // очистить дисплей lcd.print("Voltage"); } void loop() { unsigned long CalcStart = millis(); int ReadCnt = 0; InVolt = 0; // Чтение из порта с усреднением while ((millis() - CalcStart) < REFRESH_TIME) { InVolt += analogRead(PIN_VOLT); ReadCnt++; } InVolt = InVolt / ReadCnt; // Смещение 0 для конкретного ADC (подобрать или отключить) if (InVolt >0,2) Vôn += 3; // Chuyển đổi sang volt (Giá trị: 0..1023 -> (0..VRef) được chia tỷ lệ theo Mult) Volt = InVolt * VoltMult * VRef / 1023; // Xuất dữ liệu lcd.setCursor (0, 1); lcd.print(Volt); lcd.print("V "); )

Bài viết này cung cấp một sơ đồ thú vị cho những ai thích thử nghiệm và Arduino. Nó trình bày một cách đơn giản vôn kế kỹ thuật số, có thể đo lường một cách an toàn áp suất không đổi trong phạm vi từ 0 đến 30 V. Bản thân bo mạch Arduino có thể được cấp nguồn từ nguồn 9 V tiêu chuẩn.



Như bạn đã biết, bằng cách sử dụng đầu vào analog Arduino, bạn có thể đo điện áp từ 0 đến 5 V (với điện áp tham chiếu tiêu chuẩn là 5 V). Nhưng phạm vi này có thể được mở rộng bằng cách sử dụng bộ chia điện áp.


Bộ chia giảm điện áp đo được xuống mức có thể chấp nhận được đối với đầu vào analog. Sau đó, mã được viết đặc biệt sẽ tính toán điện áp thực tế.



Cảm biến analog trong Arduino phát hiện điện áp ở đầu vào analog và chuyển đổi nó thành định dạng kỹ thuật số, được cảm nhận bởi vi điều khiển. Chúng tôi kết nối một bộ chia điện áp được hình thành bởi các điện trở R1 (100K) và R2 (10K) với đầu vào analog A0. Với các giá trị điện trở này, có thể cung cấp tới 55 V cho Arduino vì hệ số phân chia là trong trường hợp này hóa ra là 11, vậy 55V/11=5V. Để đảm bảo phép đo an toàn cho bo mạch, tốt nhất nên đo điện áp trong khoảng từ 0 đến 30 V.



Nếu số đọc trên màn hình không tương ứng với số đọc của vôn kế đã được xác minh, bạn nên sử dụng máy đo độ chính xác vạn năng kỹ thuật sốđể tìm giá trị chính xác R1 và R2. Trong trường hợp này, trong mã, bạn sẽ cần thay thế R1=100000.0 và R2=10000.0 bằng các giá trị của riêng bạn. Sau đó, bạn nên kiểm tra nguồn điện bằng cách đo điện áp trên bo mạch trong khoảng từ 5V đến GND. Điện áp có thể là 4,95 V. Sau đó, trong mã vout = (giá trị * 5.0) / 1024.0, bạn cần thay thế 5.0 bằng 4,95. Nên sử dụng điện trở chính xác có sai số không quá 1%. Xin lưu ý rằng điện áp trên 55V có thể gây ra bo mạch Arduino Ngừng phục vụ!



#bao gồm LCD LiquidCrystal(7, 8, 9, 10, 11, 12); int analogInput = 0; float vout = 0,0; float vin = 0,0; phao R1 = 100000.0; // điện trở R1 (100K) float R2 = 10000.0; // điện trở R2 (10K) giá trị int = 0; void setup())( pinMode(analogInput, INPUT); lcd.begin(16, 2); lcd.print("DC VOLTMETER"); ) void loop())( // đọc giá trị analog value = analogRead(analogInput ); vout = (giá trị * 5.0) / 1024.0; vin = vout / (R2/(R1+R2)); if (vin<0.09) { vin=0.0;// обнуляем нежелательное значение } lcd.setCursor(0, 1); lcd.print("INPUT V= "); lcd.print(vin); delay(500); }


Các yếu tố được sử dụng:


Bo mạch Arduino Uno
Điện trở 100 KOhm
Điện trở 10 KOhm
điện trở 100 ohm
Chiết áp 10KOhm
Màn hình LCD 16×2

Một sơ đồ hữu ích được trình bày cho những ai thích thử nghiệm với Arduino. Đây là một vôn kế kỹ thuật số đơn giản có thể đo điện áp DC một cách đáng tin cậy trong phạm vi 0 - 30V. Bo mạch Arduino, như thường lệ, có thể được cấp nguồn bằng pin 9V.

Như bạn có thể biết, đầu vào analog của Arduino có thể được sử dụng để đo điện áp DC trong phạm vi 0 - 5V và phạm vi này có thể tăng lên,
dùng hai điện trở làm bộ chia điện áp. Bộ chia sẽ giảm điện áp đo được xuống mức đầu vào tương tự Arduino. Sau đó chương trình sẽ tính giá trị điện áp thực tế.

Cảm biến analog trên bo mạch Arduino phát hiện sự hiện diện của điện áp ở đầu vào analog và chuyển đổi nó thành dạng kỹ thuật số để vi điều khiển xử lý thêm. Trong hình, điện áp được cung cấp cho đầu vào analog (A0) thông qua một bộ chia điện áp đơn giản bao gồm các điện trở R1 (100 kOhm) và R2 (10 kOhm).

Với các giá trị chia này, bo mạch Arduino có thể được cung cấp điện áp từ 0 đến
55V. Ở đầu vào A0, chúng ta có điện áp đo được chia cho 11, tức là 55V / 11=5V. Nói cách khác, khi đo 55V ở đầu vào Arduino, ta có giá trị tối đa cho phép là 5V. Trong thực tế, tốt hơn là viết phạm vi “0 - ​​​​30V” trên vôn kế này để nó vẫn giữ nguyên
Biên độ an toàn!

Ghi chú

Nếu số đọc trên màn hình không trùng với số đọc của vôn kế công nghiệp (phòng thí nghiệm), thì cần đo giá trị của điện trở R1 và R2 bằng một dụng cụ chính xác và chèn các giá trị này thay vì R1=100000.0 và R2=10000.0 trong mã chương trình. Sau đó, bạn nên đo điện áp thực giữa chân 5V và chân “Nối đất” của bo mạch Arduino bằng vôn kế trong phòng thí nghiệm. Kết quả sẽ là giá trị nhỏ hơn 5V, ví dụ sẽ là 4,95V. Giá trị thực này phải được chèn vào dòng mã
vout = (giá trị * 5.0)/1024.0 thay vì 5.0.
Ngoài ra, hãy thử sử dụng điện trở chính xác với dung sai 1%.

Các điện trở R1 và R2 cung cấp một số biện pháp bảo vệ chống lại việc tăng điện áp đầu vào. Tuy nhiên, hãy nhớ rằng bất kỳ điện áp nào trên 55V đều có thể làm hỏng bo mạch Arduino. Ngoài ra, thiết kế này không cung cấp các loại bảo vệ khác (chống tăng điện áp, đảo cực hoặc quá điện áp).

Chương trình vôn kế kỹ thuật số

/*
Vôn kế DC
Một Arduino DVM dựa trên khái niệm bộ chia điện áp
T.K.Hareendran
*/
#bao gồm
LCD LiquidCrystal(7, 8, 9, 10, 11, 12);
int analogInput = 0;
float vout = 0,0;
float vin = 0,0;
phao R1 = 100000.0; // điện trở của R1 (100K) -xem văn bản!
phao R2 = 10000,0; // điện trở của R2 (10K) – xem văn bản!
giá trị int = 0;
thiết lập void())(
pinMode(analogInput, INPUT);
lcd.begin(16, 2);
lcd.print(“Vôn kế DC”);
}
vòng lặp trống()
// đọc giá trị ở đầu vào analog
giá trị = analogRead(analogInput);
vout = (giá trị * 5.0) / 1024.0; // xem văn bản
vin = vout / (R2/(R1+R2));
nếu (vin<0.09) {
vin=0.0;//câu lệnh để loại bỏ việc đọc không mong muốn !
}
lcd.setCursor(0, 1);
lcd.print(“INPUT V= “);
lcd.print(vin);
độ trễ (500);
}

Sơ đồ nguyên lý của vôn kế Arduino

Danh sách các thành phần

Bo mạch Arduino Uno
Điện trở 100 kOhm
Điện trở 10 kOhm
điện trở 100 ohm
Điện trở cắt 10kOhm
Màn hình LCD 16?2 (Hitachi HD44780)

Với một số bổ sung.

Một tính năng ít được biết đến của Arduino và nhiều chip AVR khác là khả năng đo điện áp tham chiếu 1,1 V bên trong. Chức năng này có thể được sử dụng cho tăng độ chính xác Chức năng Arduino - analogRead sử dụngđiện áp tham chiếu tiêu chuẩn 5 V (trên nền tảng có điện áp cung cấp 5 V) hoặc 3,3 V (trên nền tảng có điện áp cung cấp 3,3 V).Cô ấy cũng có thể dùng để đo Vcc áp dụng cho chip, cung cấp phương tiện kiểm soát điện áp pin không sử dụng chân analog quý giá.

Động lực

Có ít nhất ít nhất hai lý dođể đo Cung cấp hiệu điện thế Arduino của chúng tôi (Vcc). Một trong số đó là dự án chạy bằng pin của chúng tôi nếu chúng tôi muốn theo dõi mức điện áp của pin. Ngoài ra, khi nguồn pin (Vcc) không thể là 5,0 volt (ví dụ: nguồn điện 3 cell 1,5 V) và chúng tôi muốn thực hiện các phép đo tương tự chính xác hơn - chúng tôi phải sử dụng nguồn điện áp tham chiếu 1,1 V bên trong hoặc nguồn điện áp tham chiếu bên ngoài. Tại sao?

Người ta thường giả định khi sử dụng analogRead() rằng điện áp nguồn tương tự của bộ điều khiển là 5,0 volt, trong khi thực tế điều này có thể không xảy ra (ví dụ: nguồn điện từ 3 phần tử là 1,5 V). Tài liệu chính thức của Arduino thậm chí có thể dẫn chúng ta đến giả định không chính xác này. Thực tế là nguồn điện không nhất thiết phải là 5,0 volt, bất kể mức hiện tại như thế nào, nguồn điện này đều được cung cấp cho Vcc của chip. Nếu nguồn điện của chúng ta không ổn định hoặc nếu chúng ta đang chạy bằng nguồn pin, điện áp này có thể thay đổi một chút. Đây là một ví dụ mã minh họa vấn đề này:

Vcc kép = 5,0; // không nhất thiết phải đúng int value = analogRead(0); / đọc số đọc từ A0 double volt = (giá trị / 1023.0) * Vcc; // chỉ đúng nếu Vcc = 5,0 volt. Để đo điện áp chính xác, cần có điện áp tham chiếu chính xác. Hầu hết các chip AVR đều cung cấp ba tham chiếu điện áp:

  • 1,1 V từ nguồn nội bộ, trong tài liệu, nó chuyển dưới dạng tham chiếu băng thông (một số trong số chúng là 2,56 V, ví dụ ATMega 2560). Việc lựa chọn được thực hiện bởi hàm analogReference() với tham số INTERNAL: analogReference(INTERNAL) ;
  • nguồn điện áp tham chiếu bên ngoài, được dán nhãn AREF trên arduino. Chọn: analogReference(EXTERNAL);
  • Vcc là nguồn điện của bộ điều khiển. Chọn: analogReference(DEFAULT).

Trong Arduino, bạn không thể kết nối trực tiếp Vcc với chân analog - theo mặc định, AREF được kết nối với Vcc và bạn sẽ luôn nhận được giá trị tối đa là 1023, bất kể bạn được cấp nguồn từ điện áp nào. Việc kết nối với ISF một nguồn điện áp có điện áp ổn định đã biết trước đó sẽ giúp ích, nhưng đây là một thành phần bổ sung trong mạch.

Bạn cũng có thể kết nối Vcc với ISF thông qua điốt: Độ sụt áp trên diode đã được biết trước nên việc tính toán Vcc không khó. Tuy nhiên, với mạch như vậy thông qua một diode dòng điện chạy liên tục, rút ​​ngắn tuổi thọ pin, điều này cũng không tốt lắm.

Tham chiếu điện áp bên ngoài là chính xác nhất nhưng cần có phần cứng bổ sung. ION bên trong ổn định nhưng độ lệch không chính xác +/- 10%. Vcc hoàn toàn không đáng tin cậy trong hầu hết các trường hợp. Việc chọn tham chiếu điện áp bên trong không tốn kém và ổn định, nhưng hầu hết chúng ta muốn đo điện áp lớn hơn 1,1V, vì vậy sử dụng Vcc là cách thực tế nhất nhưng có khả năng kém chính xác nhất. Trong một số trường hợp, nó có thể rất không đáng tin cậy!

Làm thế nào để làm nó

Nhiều chip AVR bao gồm dòng ATmega và ATtiny cung cấp phương tiện đo điện áp tham chiếu bên trong. Tại sao điều này là cần thiết? Lý do rất đơn giản - bằng cách đo điện áp bên trong, chúng ta có thể xác định giá trị của Vcc. Đây là cách thực hiện:

  1. Đặt tham chiếu điện áp mặc định: analogReference(DEFAULT); . Chúng tôi sử dụng Vcc làm nguồn.
  2. Lấy số đọc ADC cho nguồn 1,1 V bên trong.
  3. Tính giá trị Vcc dựa trên phép đo 1,1 V bằng công thức:

Vcc * (đọc ADC) / 1023 = 1,1 V

Những gì sau đây:

Vcc = 1,1 V * 1023 / (đọc ADC)

Đặt mọi thứ lại với nhau và chúng tôi nhận được mã:

long readVcc() ( // Đọc tham chiếu 1.1V đối với AVcc // đặt tham chiếu thành Vcc và phép đo thành tham chiếu 1.1V bên trong #if được xác định(__AVR_ATmega32U4__) || được xác định(__AVR_ATmega1280__) || được xác định(__AVR_ATmega2560__) ADMUX = _BV (REFS0) | _BV(MUX4) | _BV(MUX3) | _BV(MUX2) | _BV(MUX1); #elif được xác định (__AVR_ATtiny24__) || được xác định(__AVR_ATtiny44__) || được xác định(__AVR_ATtiny84__) ADMUX = _BV(MUX5) | _BV (MUX0); #elif được xác định (__AVR_ATtiny25__) || được xác định(__AVR_ATtiny45__) || được xác định(__AVR_ATtiny85__) ADMUX = _BV(MUX3) | _BV(MUX2); #else ADMUX = _BV(REFS0) | _BV(MUX3) | _BV( MUX2) | _BV(MUX1); #endif delay(75); // Đợi Vref giải quyết ADCSRA |= _BV(ADSC); // Bắt đầu chuyển đổi while (bit_is_set(ADCSRA,ADSC)); // đo uint8_t low = ADCL; // phải đọc ADCL trước - sau đó nó khóa ADCH uint8_t high = ADCH; // mở cả hai kết quả dài = (cao<<8) | low; result = 1125300L / result; // Calculate Vcc (in mV); 1125300 = 1.1*1023*1000 return result; // Vcc in millivolts }

Cách sử dụng

Kiểm tra Vcc hoặc điện áp pin

Bạn có thể gọi hàm này là readVcc() nếu bạn muốn theo dõi Vcc. Một ví dụ sẽ là kiểm tra mức sạc pin. Bạn cũng có thể sử dụng nó để xác định xem bạn đang kết nối với nguồn điện hay đang chạy bằng nguồn pin.

Đo Vcc cho điện áp tham chiếu

Bạn cũng có thể sử dụng nó để lấy giá trị Vcc chính xác để sử dụng với analogRead() khi bạn đang sử dụng điện áp tham chiếu (Vcc). Trừ khi bạn sử dụng nguồn điện được điều chỉnh, bạn không thể chắc chắn rằng Vcc = 5,0 volt. Chức năng này cho phép bạn nhận được giá trị chính xác. Tuy nhiên có một lưu ý...

Trong một bài viết, tôi đã tuyên bố rằng chức năng này có thể được sử dụng để cải thiện độ chính xác của các phép đo tương tự trong trường hợp Vcc không quá 5,0 volt. Thật không may, thủ tục này sẽ không cho kết quả chính xác. Tại sao? Điều này phụ thuộc vào độ chính xác của điện áp tham chiếu bên trong. Thông số kỹ thuật đưa ra điện áp danh định là 1,1 volt, nhưng cho biết nó có thể thay đổi tới 10%. Các phép đo như vậy có thể kém chính xác hơn so với nguồn điện Arduino của chúng tôi!

Tăng độ chính xác

Mặc dù dung sai lớn của nguồn điện 1.1V bên trong hạn chế đáng kể độ chính xác của phép đo khi sử dụng trong sản xuất hàng loạt, nhưng chúng tôi có thể đạt được độ chính xác cao hơn cho các dự án tùy chỉnh. Điều này có thể dễ dàng thực hiện bằng cách đo Vcc bằng vôn kế và hàm readVcc() của chúng tôi. Tiếp theo, thay thế hằng số 1125300L bằng một biến mới:

tỉ lệ_constant = nội bộ1.1Ref * 1023 * 1000

nội bộ1.1Ref = 1,1 * Vcc1 (voltmeter_readings) / Vcc2 (readVcc_function_readings)

Giá trị hiệu chỉnh này sẽ là chỉ báo tốt cho phép đo chip AVR, nhưng có thể bị ảnh hưởng bởi sự thay đổi nhiệt độ. Hãy thử nghiệm với các phép đo của riêng bạn.

Phần kết luận

Có rất nhiều thứ bạn có thể làm với tính năng nhỏ này. Bạn có thể sử dụng điện áp tham chiếu ổn định gần 5.0V mà không thực sự có 5.0V trên Vcc. Bạn có thể đo điện áp pin hoặc thậm chí xem bạn đang chạy bằng nguồn pin hay nguồn điện cố định.

Cuối cùng, mã sẽ hỗ trợ tất cả Arduinos, bao gồm cả Leonardo mới, cũng như các chip dòng ATtinyX4 và ATtinyX5.

Đầu vào tương tự của bo mạch Arduino.

Bảng mạch Arduino UNO chứa 6 đầu vào analog được thiết kế để đo tín hiệu điện áp. Sẽ đúng hơn nếu nói rằng 6 chân của bo mạch có thể hoạt động ở cả chế độ đầu ra rời rạc và đầu vào analog.

Các chân này được đánh số từ 14 đến 19. Ban đầu chúng được cấu hình làm đầu vào tương tự và có thể được truy cập bằng tên A0-A5. Chúng có thể được cấu hình ở chế độ đầu ra riêng biệt bất cứ lúc nào.

pinMode(A3, OUTPUT); // cài đặt chế độ đầu ra rời rạc cho A3
digitalWrite(A3, THẤP); // cài đặt đầu ra A3 ở mức thấp

Để quay lại chế độ đầu vào analog:

pinMode(A3, INPUT); // cài đặt chế độ đầu vào analog cho A3

Đầu vào analog và điện trở kéo lên.

Điện trở kéo lên được kết nối với các chân đầu vào tương tự cũng như với các chân rời rạc. Các điện trở này được bật bằng lệnh

digitalWrite(A3, CAO); // bật điện trở kéo lên đầu vào A3

Lệnh phải được áp dụng cho chân được cấu hình ở chế độ đầu vào.

Cần phải nhớ rằng điện trở có thể ảnh hưởng đến mức tín hiệu đầu vào analog. Dòng điện từ nguồn điện 5V đi qua điện trở kéo lên sẽ gây ra hiện tượng sụt áp trên điện trở trong của nguồn tín hiệu. Vì vậy tốt hơn hết là ngắt kết nối điện trở.

Bộ chuyển đổi analog sang digital của bo mạch Arduino.

Việc đo điện áp thực tế ở các đầu vào được thực hiện bằng bộ chuyển đổi tương tự sang số (ADC) có công tắc cho 6 kênh. ADC có độ phân giải 10 bit, tương ứng với mã ở đầu ra của bộ chuyển đổi 0...1023. Sai số đo không quá 2 đơn vị chữ số có nghĩa nhỏ nhất.

Để duy trì độ chính xác tối đa (10 bit), điện trở trong của nguồn tín hiệu không vượt quá 10 kOhm. Yêu cầu này đặc biệt quan trọng khi sử dụng các bộ chia điện trở nối với đầu vào analog của bo mạch. Điện trở của các điện trở chia không thể quá cao.

Chức năng phần mềm đầu vào tương tự.

int analogRead(port)

Đọc giá trị điện áp ở đầu vào analog được chỉ định. Điện áp đầu vào nằm trong khoảng từ 0 đến mức điện áp tham chiếu (thường là 5 V) chuyển đổi thành mã từ 0 đến 1023.

Với điện áp tham chiếu là 5 V thì độ phân giải là 5 V/1024 = 4,88 mV.

Quá trình chuyển đổi mất khoảng 100 μs.

int inputCod; // mã điện áp đầu vào
đầu vào floatĐiện áp; // điện áp đầu vào trong V

inputCod= analogRead(A3); // đọc điện áp ở đầu vào A3
inputVoltage= ((float)inputCod * 5. / 1024.); // chuyển đổi mã thành điện áp (V)

void analogReference(type)

Đặt điện áp tham chiếu cho ADC. Nó xác định điện áp đầu vào tương tự tối đa mà ADC có thể chuyển đổi chính xác. Giá trị của điện áp tham chiếu cũng xác định hệ số chuyển đổi mã thành điện áp:

Điện áp đầu vào = mã ADC * điện áp tham chiếu/1024.

Đối số kiểu có thể nhận các giá trị sau:

  • MẶC ĐỊNH – điện áp tham chiếu bằng điện áp nguồn của bộ điều khiển (5 V hoặc 3,3 V). Đối với Arduino UNO R3 – 5V.
  • NỘI BỘ – điện áp tham chiếu bên trong 1,1 V cho bo mạch có bộ điều khiển ATmega168 và ATmega328, cho ATmega8 – 2,56 V.
  • INTERNAL1V1 – điện áp tham chiếu 1,1 V bên trong cho bộ điều khiển Arduino Mega.
  • INTERNAL2V56 – điện áp tham chiếu 2,56 V bên trong cho bộ điều khiển Arduino Mega.
  • BÊN NGOÀI – nguồn điện áp tham chiếu bên ngoài, được kết nối với đầu vào ISF.

analogReference(NỘI BỘ); // điện áp tham chiếu là 1,1 V

Vôn kế hai kênh trên Arduino.

Để làm ví dụ về việc sử dụng các hàm đầu vào tương tự, hãy tạo một dự án cho một vôn kế kỹ thuật số đơn giản trên Arduino. Thiết bị phải đo điện áp ở 2 đầu vào analog của bo mạch, đồng thời truyền giá trị đo được về máy tính qua cổng nối tiếp. Lấy dự án này làm ví dụ, tôi sẽ trình bày các nguyên tắc tạo ra các hệ thống thu thập thông tin và đo lường đơn giản.

Hãy quyết định rằng vôn kế phải đo điện áp trong phạm vi ít nhất 0...20 V và phát triển mạch kết nối các đầu vào vôn kế với bo mạch Arduino UNO.

Nếu chúng ta đặt điện áp tham chiếu thành 5 V thì đầu vào analog của bo mạch sẽ đo điện áp trong khoảng 0...5 V. Và chúng ta cần ít nhất 0...20 V. Điều này có nghĩa là chúng ta cần sử dụng một bộ chia điện áp.

Điện áp ở đầu vào và đầu ra của bộ chia có liên hệ với nhau bởi hệ thức:

Uoutput = (Uinput / (R1 + R2)) * R2

Tỷ số truyền:

K = Uoutput / Uinput = R2 / (R1 + R2)

Chúng ta cần tỷ số truyền là 1/4 (20 V * 1/4 = 5 V).

Để duy trì độ chính xác tối đa (10 bit), điện trở trong của nguồn tín hiệu không vượt quá 10 kOhm. Vì vậy ta chọn điện trở R2 bằng 4,22 kOhm. Ta tính điện trở của điện trở R1.

0,25 = 4,22 / (R1 + 4,22)
R1 = 4,22 / 0,25 – 4,22 = 12,66 kOhm

Tôi tìm thấy điện trở có điện trở 15 kOhm có giá trị gần nhất. Với điện trở R1 = 15 kOhm và R2 = 4,22:

5 / (4,22 / (15 + 4,22)) = 22,77 V.

Mạch vôn kế dựa trên Arduino sẽ trông như thế này.

Hai bộ chia điện áp được kết nối với đầu vào analog A0 và A1. Các tụ điện C1 và C2, cùng với các điện trở phân chia, tạo thành các bộ lọc thông thấp giúp loại bỏ nhiễu tần số cao khỏi tín hiệu.

Tôi lắp ráp mạch này trên một bảng mạch.

Tôi kết nối đầu vào đầu tiên của vôn kế với nguồn điện được điều chỉnh và đầu vào thứ hai với nguồn điện 3,3 V của bo mạch Arduino. Để theo dõi điện áp, tôi nối một vôn kế với đầu vào đầu tiên. Tất cả những gì còn lại là viết chương trình.

Một chương trình đo điện áp bằng bảng Arduino.

Thuật toán rất đơn giản. Cần thiết:

  • đọc mã ADC hai lần mỗi giây;
  • chuyển đổi nó thành điện áp;
  • gửi giá trị đo được qua cổng nối tiếp tới máy tính;
  • Chương trình giám sát cổng Arduino IDE hiển thị các giá trị điện áp thu được trên màn hình máy tính.

Tôi sẽ cung cấp cho bạn bản phác thảo hoàn chỉnh của chương trình ngay lập tức.

// chương trình đo điện áp
// trên đầu vào analog A0 và A1

#bao gồm

khoảng thời gian đo
#define R1 15. // điện trở R1
#define R2 4.22 // điện trở R2


thả nổi u1, u2; // đo điện áp

thiết lập void() (
Serial.begin(9600); //

MsTimer2::start(); // kích hoạt ngắt
}

vòng lặp trống() (

// khoảng thời gian 500 mili giây
if (timeCount >= MEASURE_PERIOD) (
timeCount= 0;

//

// đọc mã kênh 2 và chuyển đổi thành điện áp
u2= ((float)analogRead(A1)) * 5. / 1024. / R2 * (R1 + R2);

// truyền dữ liệu qua cổng nối tiếp
Serial.print("U1 = "); Serial.print(u1, 2);
Serial.print(" U2 = "); Serial.println(u2, 2);
}
}

// xử lý ngắt 1 ms
void hẹn giờInterrupt() (
thời gianCount++;
}

Hãy để tôi giải thích dòng mã ADC được chuyển đổi thành điện áp:

// đọc mã kênh 1 và chuyển đổi thành điện áp
u1= ((float)analogRead(A0)) * 5. / 1024. / R2 * (R1 + R2);

  • Mã ADC được đọc: analogRead(A0) .
  • Được chuyển đổi rõ ràng sang định dạng dấu phẩy động: (float) .
  • Chuyển đổi thành điện áp ở đầu vào analog: * 5. / 1024. Dấu chấm ở cuối các số cho biết đây là số dấu phẩy động.
  • Hệ số truyền của bộ chia được tính đến: /R2*(R1 + R2).

Hãy tải chương trình vào bo mạch và khởi chạy màn hình cổng nối tiếp.

Hai thanh chạy hiển thị giá trị của điện áp đo được. Mọi thứ đang hoạt động.

Đo giá trị tín hiệu trung bình.

Hãy kết nối kênh đầu tiên của vôn kế của chúng ta với nguồn điện áp có mức gợn sóng cao. Chúng ta sẽ thấy hình ảnh này trên màn hình.

Các giá trị điện áp của kênh đầu tiên trên màn hình điều khiển liên tục co giật và nhảy vọt. Và số đọc của vôn kế điều khiển khá ổn định. Điều này là do vôn kế tham chiếu đo giá trị trung bình của tín hiệu, trong khi bo mạch Arduino đọc các mẫu riêng lẻ cứ sau 500 ms. Đương nhiên, thời điểm ADC đọc rơi vào các điểm khác nhau trong tín hiệu. Và ở mức xung cao, biên độ tại các điểm này sẽ khác nhau.

Ngoài ra, nếu tín hiệu được đọc trong các mẫu thưa thớt riêng biệt thì bất kỳ nhiễu xung nào cũng có thể gây ra sai số đáng kể trong phép đo.

Giải pháp là lấy một số mẫu thường xuyên và lấy giá trị trung bình đo được. Đối với điều này:

  • trong trình xử lý ngắt, chúng tôi đọc mã ADC và tính tổng nó với các mẫu trước đó;
  • đếm thời gian lấy trung bình (số lượng mẫu lấy trung bình);
  • khi đạt đến số lượng mẫu được chỉ định, chúng tôi lưu tổng giá trị của mã ADC;
  • Để có được giá trị trung bình, hãy chia tổng mã ADC cho số lượng mẫu trung bình.

Bài toán trong sách giáo khoa toán lớp 8. Đây là bản phác thảo của chương trình, một vôn kế có giá trị trung bình hai kênh.

// chương trình đo trung thế
// trên đầu vào analog A0 và A1

#bao gồm

#define MEASURE_PERIOD 500 // khoảng thời gian đo
#define R1 15. // điện trở R1
#define R2 4.22 // điện trở R2

int timeCount; // bộ đếm thời gian
tổng dàiU1, tổngU2; // các biến để tính tổng mã ADC
avarageU1 dài, avarageU2; // tổng mã ADC (giá trị trung bình * 500)
cờ booleanSẵn sàng; // chỉ báo mức độ sẵn sàng của dữ liệu đo lường

thiết lập void() (
Serial.begin(9600); // khởi tạo cổng, tốc độ 9600
MsTimer2::set(1, timeInterupt); // ngắt hẹn giờ, khoảng thời gian 1 ms
MsTimer2::start(); // kích hoạt ngắt
}

vòng lặp trống() (

if (flagReady == true) (
flagReady= sai;
// chuyển đổi thành điện áp và truyền vào máy tính
Serial.print("U1 = ");
Serial.print((float)avarageU1 / 500. * 5. / 1024. / R2 * (R1 + R2), 2);
Serial.print(" U2 = ");
Serial.println((float)avarageU2 / 500. * 5. / 1024. / R2 * (R1 + R2), 2);
}
}

// xử lý ngắt 1 ms
void hẹn giờInterrupt() (

thời gianCount++; // +1 bộ đếm mẫu trung bình
sumU1+= analogRead(A0); // tổng hợp mã ADC
sumU2+= analogRead(A1); // tổng hợp mã ADC

// kiểm tra số lượng mẫu trung bình
if (timeCount >= MEASURE_PERIOD) (
timeCount= 0;
avarageU1= sumU1; // quá tải giá trị trung bình
avarageU2= sumU2; // quá tải giá trị trung bình
tổngU1= 0;
tổngU2= 0;
flagReady= đúng; // kết quả đo dấu hiệu đã sẵn sàng
}
}

Trong công thức chuyển đổi mã ADC thành điện áp, /500 đã được thêm vào - số lượng mẫu. Tải, khởi chạy trình giám sát cổng (Cntr+Shift+M).

Bây giờ, ngay cả với mức độ xung đáng kể, số đọc vẫn thay đổi hàng phần trăm. Nguyên nhân là do điện áp không ổn định.

Số lượng mẫu phải được chọn có tính đến:

  • số lượng mẫu quyết định thời gian đo;
  • Số lượng mẫu càng lớn thì độ nhiễu sẽ càng nhỏ.

Nguồn gây nhiễu chính trong tín hiệu analog là mạng 50 Hz. Do đó, nên chọn thời gian trung bình là bội số của 10 ms – thời gian nửa chu kỳ của mạng 50 Hz.

Tối ưu hóa tính toán.

Tính toán dấu phẩy động chỉ đơn giản là tiêu tốn tài nguyên của bộ vi điều khiển 8 bit. Bất kỳ thao tác dấu phẩy động nào đều yêu cầu không chuẩn hóa mantissa, thao tác điểm cố định, chuẩn hóa mantissa, sửa thứ tự... Và tất cả các thao tác với số 32 bit. Vì vậy, cần hạn chế tối đa việc sử dụng các phép tính dấu phẩy động. Tôi sẽ cho bạn biết cách thực hiện điều này trong các bài học sau, nhưng ít nhất hãy tối ưu hóa các phép tính của chúng ta. Hiệu quả sẽ rất đáng kể.

Trong chương trình của chúng tôi, việc chuyển đổi mã ADC thành điện áp được viết như sau:

(float)trung bìnhU1 / 500. * 5. / 1024. / R2 * (R1 + R2)

Có rất nhiều phép tính ở đây, tất cả đều có dấu phẩy động. Nhưng hầu hết các phép tính đều là các phép tính với hằng số. Một phần của dòng:

/ 500. * 5. / 1024. / R2 * (R1 + R2)

(phao)trung bìnhU1 * 0,00004447756

Bản thân các trình biên dịch thông minh nhận dạng các phép tính bằng hằng số và tính toán chúng ở giai đoạn biên dịch. Tôi có câu hỏi về trình biên dịch của Andruino thông minh đến mức nào. Tôi đã quyết định kiểm tra nó.

Tôi đã viết một chương trình ngắn. Nó thực hiện một chu kỳ 10.000 lượt và sau đó truyền thời gian thực hiện của 10.000 chu kỳ đó đến máy tính. Những thứ kia. nó cho phép bạn xem thời gian thực hiện của các thao tác được đặt trong phần thân vòng lặp.

// kiểm tra tối ưu hóa tính toán

int x= 876;
thả nổi y;
số int không dấu;
không dấu thời gian dài Hiện tại, timePrev;

thiết lập void() (
Serial.begin(9600);
}

vòng lặp trống() (
đếm++;
// y= (float)x / 500. * 5. / 1024. / 4.22 * (15. + 4.22);
// y= (float)x * 0,00004447756 ;

nếu (đếm >= 10000) (
đếm= 0;
timeCurrent= millis();
Serial.println(timeCurrent - timePrev);
timePrev= thời gian hiện tại;
}
}

Trong tùy chọn đầu tiên, khi các thao tác dấu phẩy động trong vòng lặp được nhận xét và không được thực thi, chương trình tạo ra kết quả là 34 mili giây.

Những thứ kia. 10.000 vòng lặp trống được hoàn thành trong 34 mili giây.

Sau đó tôi mở dòng:

y= (float)x / 500. * 5. / 1024. / 4.22 * (15. + 4.22);

lặp lại tính toán của chúng tôi Kết quả của 10.000 lần vượt qua trong 922 mili giây hoặc

(922 – 34) / 10.000 = 88,8 µs.

Những thứ kia. dòng tính toán dấu phẩy động này mất 89 µs để hoàn thành. Tôi nghĩ sẽ có nhiều hơn nữa.

Bây giờ tôi đóng dòng này bằng một nhận xét và mở dòng tiếp theo, nhân với hằng số được tính toán trước:

y= (float)x * 0,00004447756 ;

Kết quả của 10.000 lần vượt qua trong 166 mili giây hoặc

(166 – 34) / 10.000 = 13,2 µs.

Kết quả đáng kinh ngạc. Chúng tôi đã tiết kiệm được 75,6 μs trên mỗi dòng. Chúng tôi đã hoàn thành nó nhanh hơn gần 7 lần. Chúng tôi có 2 dòng như vậy, nhưng có thể có nhiều dòng hơn trong chương trình.

Kết luận - việc tính toán với các hằng số phải được thực hiện độc lập trên máy tính và sử dụng trong các chương trình dưới dạng hệ số có sẵn. Trình biên dịch Arduino sẽ không tính toán chúng ở giai đoạn biên dịch. Trong trường hợp của chúng tôi, chúng tôi nên làm điều này:

#define ADC_U_COEFF 0,00004447756 // hệ số chuyển đổi mã ADC thành điện áp

Serial.print((float)avarageU1 * ADC_U_COEFF, 2);

Tùy chọn tối ưu cho hiệu suất là chuyển mã ADC vào máy tính và cùng với đó là tất cả các phép tính dấu phẩy động. Trong trường hợp này, một chương trình chuyên biệt trên máy tính phải nhận dữ liệu. Trình giám sát cổng từ Arduino IDE sẽ không hoạt động.

Tôi sẽ nói về những cách khác để tối ưu hóa chương trình Arduino trong các bài học sau nếu cần. Nhưng không giải quyết được vấn đề này thì không thể phát triển các chương trình phức tạp trên bộ vi điều khiển 8 bit.

Một bài học khác đã xuất hiện trên trang web (