תוכן עניינים:

Arduino ו- PCF8591 ADC DAC IC: 7 שלבים
Arduino ו- PCF8591 ADC DAC IC: 7 שלבים

וִידֵאוֹ: Arduino ו- PCF8591 ADC DAC IC: 7 שלבים

וִידֵאוֹ: Arduino ו- PCF8591 ADC DAC IC: 7 שלבים
וִידֵאוֹ: Output DC or AC Voltage using MCP4725 DAC with LCD and PWM to Voltage Converter with Arduino 2024, יולי
Anonim
Arduino ו- PCF8591 ADC DAC IC
Arduino ו- PCF8591 ADC DAC IC

האם אי פעם רצית יותר סיכות קלט אנלוגיות בפרויקט הארדואינו שלך, אבל לא רצית לזייף מגה? או שתרצה ליצור אותות אנלוגיים? לאחר מכן בדוק את נושא ההדרכה שלנו - ה- NXP PCF8591 IC.

הוא פותר את שתי הבעיות הללו מכיוון שיש לו ממיר DAC יחיד (דיגיטלי לאנלוגי) וכן ארבעה ADC (ממירים אנלוגיים לדיגיטליים) - כולם נגישים באמצעות אוטובוס I2C. ה- PCF8591 זמין בצורת DIP, הרכבה על פני השטח ומודול, מה שמקל על הניסוי.

לפני שתמשיך הלאה, הורד את גליון הנתונים. ה- PCF8591 יכול לפעול הן על 5V והן על 3.3V, כך שאם אתה משתמש ב- Arduino Due, Raspberry Pi או לוח פיתוח אחר של 3.3V אתה בסדר. כעת נסביר תחילה את ה- DAC, ולאחר מכן את ה- ADC.

שלב 1: שימוש ב- DAC (ממיר דיגיטלי לאנלוגי)

שימוש ב- DAC (ממיר דיגיטלי לאנלוגי)
שימוש ב- DAC (ממיר דיגיטלי לאנלוגי)

ל- DAC ב- PCF8591 יש רזולוציה של 8 סיביות-כך שהוא יכול לייצר אות תיאורטי של בין אפס וולט למתח ההתייחסות (Vref) ב -255 שלבים. למטרות הדגמה נשתמש ב- Vref של 5V, ותוכל להשתמש ב- Vref נמוך יותר כגון 3.3V או מה שתרצה שהערך המרבי יהיה … אולם הוא חייב להיות נמוך יותר ממתח האספקה.

שים לב שכאשר יש עומס על הפלט האנלוגי (מצב בעולם האמיתי), מתח המוצא המרבי יירד-גליון הנתונים (שהורדת) מראה ירידה של 10% בעומס של 10kΩ. עכשיו למעגל ההדגמות שלנו.

שים לב לשימוש בנגדי משיכה של 10kΩ באוטובוס I2C, ובקבל 10μF בין 5V ל- GND. כתובת האוטובוס I2C נקבעת על ידי שילוב של סיכות A0 ~ A2, וכולן ל- GND הכתובת היא 0x90. את הפלט האנלוגי ניתן לקחת מהפין 15 (ויש GND אנלוגי נפרד על סיכה 13. כמו כן, חבר את פין 13 ל- GND, והעבר את ה- GND ל- Arduino GND.

כדי לשלוט ב- DAC עלינו לשלוח שני בתים של נתונים. הראשון הוא בית הבקרה, שפשוט מפעיל את ה- DAC והוא 1000000 (או 0x40) והבייט הבא הוא הערך בין 0 ל -255 (רמת הפלט). זה מודגם במערכון הבא:

// דוגמה 52.1 PCF8591 הדגמת DAC

#כלול "Wire.h" #define PCF8591 (0x90 >> 1) // כתובת אוטובוס I2C הגדרת חלל () {Wire.begin (); } לולאת void () {for (int i = 0; i <256; i ++) {Wire.beginTransmission (PCF8591); // להעיר PCF8591 Wire.write (0x40); // בית בקרה - הפעל DAC (בינארי 1000000) Wire.write (i); // ערך לשלוח ל- DAC Wire.endTransmission (); // סוף טרנסמינשן}

עבור (int i = 255; i> = 0; --i)

{Wire.beginTransmission (PCF8591); // להעיר PCF8591 Wire.write (0x40); // בית בקרה - הפעל DAC (בינארי 1000000) Wire.write (i); // ערך לשלוח ל- DAC Wire.endTransmission (); // סוף טרנסמינשן}}

האם שמת לב לשינוי הסיביות של כתובת האוטובוס בהצהרה #define? ארדואינו שולח כתובות של 7 סיביות אבל ה- PCF8591 רוצה 8 סיביות, אז אנחנו מעבירים את הבייט בביט אחד.

שלב 2:

תמונה
תמונה

תוצאות הסקיצה מוצגות בתמונה, חיברנו את ה- Vref ל- 5V ואת בדיקת האוסילוסקופ ו- GND לפלט האנלוגי ו- GND בהתאמה.

שלב 3:

תמונה
תמונה

אם אתה אוהב עקומות אתה יכול ליצור גלי סינוס בעזרת הסקיצה שלהלן. הוא משתמש בטבלת חיפוש במערך המכיל את נקודות הנתונים המחושבות מראש:

// דוגמה 52.2 PCF8591 הדגמת DAC - גל סינוס

#כלול "Wire.h" #הגדר PCF8591 (0x90 >> 1) // כתובת אוטובוס I2C uint8_t sine_wave [256] = {0x80, 0x83, 0x86, 0x89, 0x8C, 0x90, 0x93, 0x96, 0x99, 0x9C, 0x9F, 0xA2, 0xA5, 0xA8, 0xAB, 0xAE, 0xB1, 0xB3, 0xB6, 0xB9, 0xBC, 0xBF, 0xC1, 0xC4, 0xC7, 0xC9, 0xCC, 0xCE, 0xD1, 0xD3, 0xD 0, 0xD, 0xD 0xE2, 0xE4, 0xE6, 0xE8, 0xEA, 0xEB, 0xED, 0xEF, 0xF0, 0xF1, 0xF3, 0xF4, 0xF5, 0xF6, 0xF8, 0xF9, 0xFA, 0xFA, 0xFB, 0xF, 0xF, 0xF, 0xF, 0xF, 0xF 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE, 0xFE, 0xFE, 0xFD, 0xFD, 0xFC, 0xFB, 0xFA, 0xFA, 0xF9, 0xF8, 0xF6, 0xF5, 0xF0, 0xF 0xED, 0xEB, 0xEA, 0xE8, 0xE6, 0xE4, 0xE2, 0xE0, 0xDE, 0xDC, 0xDA, 0xD8, 0xD5, 0xD3, 0xD1, 0xCE, 0xCC, 0xC9, 0xC7, 0xB9, 0xB, 0xB 0xB3, 0xB1, 0xAE, 0xAB, 0xA8, 0xA5, 0xA2, 0x9F, 0x9C, 0x99, 0x96, 0x93, 0x90, 0x8C, 0x89, 0x86, 0x83, 0x80, 0x7D, 0x7, 0x6, 0x6, 0x6 0x67, 0x64, 0x61, 0x5E, 0x5B, 0x58, 0x55, 0x52, 0x4F, 0x4D, 0x4A, 0x47, 0x44, 0x41, 0x3F, 0x 3C, 0x39, 0x37, 0x34, 0x32, 0x2F, 0x2D, 0x2B, 0x28, 0x26, 0x24, 0x22, 0x20, 0x1E, 0x1C, 0x1A, 0x18, 0x16, 0x15, 0x13, 0x11, 0x0, 0x0, 0x0, 0x0 0x0B, 0x0A, 0x08, 0x07, 0x06, 0x06, 0x05, 0x04, 0x03, 0x03, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x0, 0x0, 0x0, 0x0, 0x2 0x04, 0x05, 0x06, 0x06, 0x07, 0x08, 0x0A, 0x0B, 0x0C, 0x0D, 0x0F, 0x10, 0x11, 0x13, 0x15, 0x16, 0x18, 0x1A, 0x1C, 0x0, 0x, 0x, 0x, 0x2B, 0x2D, 0x2F, 0x32, 0x34, 0x37, 0x39, 0x3C, 0x3F, 0x41, 0x44, 0x47, 0x4A, 0x4D, 0x4F, 0x52, 0x55, 0x58, 0x5B, 0x5, 0x6, 0x6, 0x6, 0x6 0x70, 0x74, 0x77, 0x7A, 0x7D}; הגדרת חלל () {Wire.begin (); } לולאת חלל () {עבור (int i = 0; i <256; i ++) {Wire.beginTransmission (PCF8591); // להעיר PCF8591 Wire.write (0x40); // בית בקרה - הפעל DAC (בינארי 1000000) Wire.write (sinus_wave ); // ערך לשלוח ל- DAC Wire.endTransmission (); // סוף טרנסמינשן}}

שלב 4:

תמונה
תמונה

עבור dump התמונה הבאה של DSO, שינינו את ה- Vref ל- 3.3V - שים לב לשינוי המקסימלי בגל הסינוס.

כעת תוכל להתנסות ב- DAC כדי ליצור אפקטים קוליים, אותות או לשלוט במעגלים אנלוגיים אחרים.

שלב 5: שימוש ב- ADC (ממירים אנלוגיים לדיגיטליים)

אם השתמשת בפונקציה analogRead () ב- Arduino שלך (חזרה בפרק הראשון) אז אתה כבר מכיר ADC. ללא PCF8591 נוכל לקרוא מתח בין אפס ל- Vref והוא יחזיר ערך בין אפס ל -255 שהוא ביחס ישר לאפס לבין ה- Vref.

לדוגמה, מדידת 3.3V צריכה להחזיר 168. הרזולוציה (8 סיביות) של ה- ADC נמוכה יותר מהארדואינו המשולב (10 סיביות) אולם ה- PCF8591 יכול לעשות משהו שה- ADC של Arduino לא יכול. אבל עוד מעט נגיע לזה. ראשית, כדי פשוט לקרוא את הערכים של כל סיכת ADC אנו שולחים בית בקרה כדי לספר ל- PCF8591 איזה ADC אנו רוצים לקרוא. עבור ADCs אפס עד שלוש, בית הבקרה הוא 0x00, 0x01, ox02 ו- 0x03 בהתאמה.

לאחר מכן אנו מבקשים שני בתים של נתונים בחזרה מה- ADC, ושומרים את הבייט השני לשימוש. למה שני בייטים? ה- PCF8591 מחזיר תחילה את הערך שנמדד קודם - ולאחר מכן את הבייט הנוכחי. (ראה איור 8 בגיליון הנתונים). לבסוף, אם אינך משתמש בכל סיכות ה- ADC, חבר את אלה שאינם בשימוש ל- GND. שרטוט הדוגמה הבא פשוט מאחזר ערכים מכל סיכת ADC אחד בכל פעם ולאחר מכן מציג אותם בצג הטורי:

#כלול "Wire.h"

#define PCF8591 (0x90 >> 1) // כתובת אוטובוס I2C #הגדר ADC0 0x00 // בתים בקרה לקריאת ADC בודדים #define ADC1 0x01 #define ADC2 0x02 #define ADC3 0x03 byte value0, value1, value2, value3; הגדרת חלל () {Wire.begin (); Serial.begin (9600); } לולאת חלל () {Wire.beginTransmission (PCF8591); // להעיר PCF8591 Wire.write (ADC0); // בית בקרה - קרא ADC0 Wire.endTransmission (); // סיום השידור Wire.requestFrom (PCF8591, 2); value0 = Wire.read (); value0 = Wire.read (); שידור Wire.beginTransmission (PCF8591); // להעיר PCF8591 Wire.write (ADC1); // בית בקרה - קרא ADC1 Wire.endTransmission (); // סיום השידור Wire.requestFrom (PCF8591, 2); value1 = Wire.read (); value1 = Wire.read (); שידור Wire.beginTransmission (PCF8591); // להעיר PCF8591 Wire.write (ADC2); // בית בקרה - קרא ADC2 Wire.endTransmission (); // סיום השידור Wire.requestFrom (PCF8591, 2); value2 = Wire.read (); value2 = Wire.read (); שידור Wire.beginTransmission (PCF8591); // להעיר PCF8591 Wire.write (ADC3); // בית בקרה - קרא ADC3 Wire.endTransmission (); // סיום השידור Wire.requestFrom (PCF8591, 2); value3 = Wire.read (); value3 = Wire.read (); Serial.print (value0); Serial.print (""); Serial.print (value1); Serial.print (""); Serial.print (value2); Serial.print (""); Serial.print (value3); Serial.print (""); Serial.println (); }

בעת הפעלת הסקיצה יוצגו לך הערכים של כל ADC במסך הטורי. למרות שזו הייתה הדגמה פשוטה להראות לך כיצד לקרוא בנפרד כל ADC, זוהי שיטה מסורבלת לקבל יותר מבייט אחד בכל פעם מ- ADC מסוים.

שלב 6:

לשם כך, שנה את בית הבקרה לבקשת תוספת אוטומטית, אשר מתבצעת על ידי הגדרת ביט 2 של בית הבקרה ל- 1. אז כדי להתחיל מ- ADC0 אנו משתמשים בבת בקרה חדשה של 00000100 בינארית או 0x04 הקסדצימלי. לאחר מכן בקש חמישה בתים של נתונים (שוב אנו מתעלמים מהבייט הראשון) שיגרום ל- PCF8591 להחזיר את כל הערכים בשרשרת בתים אחת. תהליך זה מודגם במערכון הבא:

#כלול "Wire.h"

#define PCF8591 (0x90 >> 1) // I2C כתובת אוטובוס ערך 0, ערך 1, ערך 2, ערך 3; הגדרת חלל () {Wire.begin (); Serial.begin (9600); } לולאת חלל () {Wire.beginTransmission (PCF8591); // להעיר PCF8591 Wire.write (0x04); // בית בקרה - קרא ADC0 ואז תגדיל אוטומטית Wire.endTransmission (); // סיום השידור Wire.requestFrom (PCF8591, 5); value0 = Wire.read (); value0 = Wire.read (); value1 = Wire.read (); value2 = Wire.read (); value3 = Wire.read (); Serial.print (value0); Serial.print (""); Serial.print (value1); Serial.print (""); Serial.print (value2); Serial.print (""); Serial.print (value3); Serial.print (""); Serial.println (); }

בעבר הזכרנו כי ה- PCF8591 יכול לעשות משהו שה- ADC של Arduino לא יכול, וזה מציע ADC דיפרנציאלי. בניגוד לקצה האחד של הארדואינו (כלומר הוא מחזיר את ההפרש בין מתח האות החיובי ל- GND, ה- ADC הדיפרנציאלי מקבל שני אותות (שאין צורך בהכרח להפנות אותם לקרקע), ומחזיר את ההפרש בין שני האותות. זה יכול להיות נוח למדידת שינויים קטנים במתח עבור תאי עומס וכן הלאה.

שלב 7:

תמונה
תמונה

הגדרת ה- PCF8591 עבור ADC דיפרנציאלי היא עניין פשוט של שינוי בית הבקרה. אם אתה עובר לדף שבע בגיליון הנתונים, שקול את הסוגים השונים של תכנות קלט אנלוגי. בעבר השתמשנו במצב '00' עבור ארבע כניסות, אולם תוכל לבחור באחרים המאוירים בבירור, למשל התמונה.

אז כדי להגדיר את בית הבקרה לשתי כניסות דיפרנציאליות, השתמש ב- 00110000 בינארי או 0x30. אז זה פשוט לבקש את בתים של נתונים ולעבוד איתם. כפי שאתה יכול לראות יש גם שילוב יחיד/דיפרנציאלי וקלט תלת-דיפרנציאלי מורכב. עם זאת נשאיר אותם לעת עתה.

אני מקווה שמצאת את זה מעניין, בין אם הוספת DAC לניסויים שלך או אם תלמד קצת יותר על ADC. אנא שקול להזמין את PCF8591 שלך מ- PMD Way.

את הפוסט הזה הביאה לכם pmdway.com - הכל ליצרנים ולחובבי האלקטרוניקה, עם משלוח חינם לכל רחבי העולם.

מוּמלָץ: