בפוסט זה נחבר לארדואינו רכיב ממשפחת LM35 – חיישני טמפרטורה קטנים וזולים שמותאמים למדידה של מעלות בסולם צלזיוס – וניצור מדחום אלקטרוני, שבודק את הטמפרטורה בחדר, שולח את המידע למחשב, ואפילו מאפשר למשתמש לקבוע דרך המחשב את פרק הזמן שיעבור בין מדידה למדידה!
כמובן, לא חסרים רכיבים למדידת טמפרטורה, ולא חייבים לבחור דווקא ב-LM35. זהו פשוט רכיב זול ונפוץ מאד – אני רכשתי שניים באיביי תמורת שני דולרים. אם אתם בוחרים בדגם אחר, אל תשכחו לקרוא את המפרט הטכני שלו ולשנות את החיווט והתוכנה בהתאם. אפרופו, כדי למצוא מפרט טכני של רכיב כלשהו, פשוט הקלידו במנוע חיפוש את הקוד שלו ואת המילה Datasheet. כך גם אפשר למצוא מידע על שבבים ורכיבים לא מזוהים נוספים שעקרנו מתוך מעגלים ישנים.
חומרה
בתמונה הבאה מוצג המעגל בשלמותו. הרכיב הכחול הוא לוח ארדואינו מסוג Nano, שהוא בעיקרון פשוט גרסה מוקטנת של הלוחות Uno ו-Duemilanove. אמנם אין לו חיבור ייעודי לסוללה והוא זקוק למטריצה או לוח PCB כבסיס, אבל הוא חוסך מקום, אפשר להשיג אותו קצת יותר בזול מאחיו הגדולים והוא די נוח לשימוש.
חיברתי לארדואינו שלושה חוטים: חוט שחור ל-GND, חוט אדום ל-5V וחוט צהוב לכניסה האנלוגית A0. כל החוטים הללו מתחברים גם ל-LM35 הזעיר שבפינת המטריצה, וחשוב מאד להקפיד על חיבור החוטים לרגלי הרכיב הנכונות, אחרת הוא יעשה לכם בעיות רציניות. במבט מלמעלה, הרכיב נראה שטוח מצד אחד ובעל "בטן" מצדו השני; אם נחשוב על הצדדים האלה כעל גב וכרס של איש, אז ה-GND הולך לרגל הימנית שלו. המתח הולך לשמאלית, וה…רגל האמצעית היא הפלט. שימו לב שהמרחק בין רגלי ה-LM35 קטן יותר מזה שבין חורי המטריצה, כך שנאלצתי לכופף את הרגל האמצעית למעלה שלא תפריע. כל כיפוף כזה מחליש את המתכת, עד שבסוף היא נשברת. אל תגידו שלא הזהרתי!
למעשה, יש שתי דרכים לשלב LM35 במעגל, כל אחת מהן מתאימה למדידת טווח טמפרטורות אחר. החיווט שבתמונה הוא הבסיסי ביותר, והוא מיועד למדידה של 0-100 מעלות צלזיוס. [עריכה: לא, זה מה שקורה כשלא קוראים את המפרט בתשומת לב… הרכיב שהשתמשתי בו כאן הוא LM35DZ שמתאים אך ורק לטווח 0-100 מעלות צלסיוס]. ה-LM35 מתנהג כמו חיישנים פאסיביים רבים אחרים, ופשוט מעביר לפלט חלק מהחשמל שמגיע אליו, בהתאם למידת החום בסביבתו. הקשר בין החום להולכת החשמל הוא לינארי: על פי המפרט, כל מעלה נוספת "משחררת" עוד 10 מיליוולט, מה שמאפשר לנו לגלות את הטמפרטורה באמצעות חישוב פשוט שנראה מיד.
תוכנה
כאמור, פרויקט זה כולל תקשורת בזמן אמת עם המחשב, ולכן נאתחל את החיבור הטורי בפונקציית האתחול:
void setup() { Serial.begin(9600); }
לארדואינו יש מספר חיבורים שנקראים "אנלוגיים", אך מבחינתנו, הם לא באמת אנלוגיים: המתחים שמגיעים אליהם, בטווח של 0-5 וולט, מומרים למספרים שלמים בטווח של 0 עד 1023 (עשרה ביטים) בלבד. כלומר, הרזולוציה של החיבורים האנלוגיים היא כמעט 0.005 וולט – או חצי מעלה צלזיוס, בפלט של החיישן שלנו.
כדי לתרגם את הקלט לטמפרטורה, פשוט נחלק מעלה (10 מיליוולט) ברזולוציה המדויקת של חיבור הקלט (5 חלקי 1024, שזה 0.0048828125*) ונחלק את הקלט בתוצאה. אפשר גם להכפיל בהופכי, זה לא משנה:
float celsius; celsius = analogRead(A0) / 2.048; Serial.println(celsius); delay(interval);
השורה הלפני-אחרונה מדפיסה את התוצאה לחיבור הטורי, והאחרונה ממתינה פרק זמן כלשהו. את המשתנה interval הגדרתי בתחילת הקוד עם ערך ברירת מחדל, כך:
unsigned int interval = 1000;
עכשיו מגיע החלק האינטראקטיבי. בעזרת פונקציות הקריאה של Serial, אנחנו יכולים לקבל מהמשתמש ערכים חדשים עבור interval. את כל הקוד המתאים הכנסתי לפונקציה נפרדת שנקראת getNewInterval. בתוך loop, אנחנו בודקים אם המשתמש שלח משהו ואם כן, קוראים לפונקציה הזו:
if (Serial.available() > 0) getNewInterval();
בתוך הפונקציה עצמה, אנחנו קוראים ומפענחים את הערך החדש מתוך הבייטים שמתקבלים דרך החיבור הטורי. צריך לזכור שני דברים חשובים: ראשית, כשאנחנו כותבים 1 בחלון החיבור הטורי של סביבת הפיתוח, הארדואינו רואה זאת לא בתור המספר 1 אלא בתור 49, שזה קוד ASCII של התו שהוקש. שנית, אם המשתמש כתב 123 ולחץ על Send, נקבל שלושה בייטים ברצף.
קוד הפונקציה אמור להיות כעת מובן מאליו. שימו לב שלא ביצעתי בו שום בדיקה של תקינות הקלט, וזה דבר שאסור לוותר עליו ביישומים אמיתיים. כאן, לצורך הפשטות והדוגמה בלבד, הרשיתי לעצמי להתרשל:
void getNewInterval() { interval = 0; while(Serial.available() > 0) interval = interval * 10 + Serial.read() - 48; Serial.print("Interval (MS) = "); Serial.println(interval); }
את הקוד המלא לפרויקט אפשר להוריד מכאן. תגובות, שאלות וכו' יתקבלו, כרגיל, בברכה.
* תוספת: חזרתי לרשומה הזו אחרי המון זמן וגיליתי את הטעות הקטנה – חישוב הרזולוציה של הקלט האנלוגי צריך להיעשות בחלוקה של 5 ב-1023, לא ב-1024. זה אומר שכל צעד מייצג 0.0048875855 מיליוולט, ומכאן שבחישוב המעלות צריך לחלק את הקלט הגולמי ב-2.046 ולא כפי שנכתב. זהו כמובן הבדל זעיר, ובכל זאת כדאי לדייק!
האם יש חיישן טמפ' מדויק יותר מחצי מעלה שאני יכול לחבר לארדוינו
מן הסתם יש חיישנים מדויקים בשוק, אבל הם יהיו יקרים מאד ואולי יצריכו כוונון וגם הקריאה מהם לא תהיה פשוטה.
אני עוד לא נתקלתי בפתרון סביר לבעיה הזו.
שלום,
אפשר לדעת איך מתכנתים את ארדואינו ?
איך מכניסים את הקוד ? ובאיזה שפה מתכנתים אותו ?
צריך להוריד את סביבת הפיתוח לארדואינו מכאן:
http://arduino.cc/en/Main/Software
התכנות נעשה בה בשפה שהיא כמעט בדיוק C, והקובץ המקומפל מועבר לארדואינו דרך USB.
קצת מוזר, זה מה שאני מקבל בפלט:
146.00
140.63
133.79
132.81
139.65
150.39
155.76
150.39
140.63
137.21
145.51
מה פה קרה פה?
או שהרכיב קצת שונה, או שהקוד קצת שונה… 🙂
כשאתה לוחץ את הרכיב בין האצבעות, הטמפרטורה הנמדדת עולה?
על הרכיב מאחורה כתוב LM35. הקוד נלקח אחד לאחד מהאתר,
ואכן – הטמפרטורה עולה כשאני לוחץ את הרכיב בין האצבעות…
איכשהו, העליתי שוב את הקוד, וזה הסתדר. מוזר!
התכוונתי לכתוב לך שיש כמה סוגים של LM35… אבל אם הסתדר, לא נוגעים 🙂
זה קטע זה.
אגב, אחרי כמה דקות הוא מתחיל לזרוק ערכים אקראיים לגמרי בטווחים שבין 10 ל 50. זה כשהטמפרטורה בחדר היא 23 (אם לסמוך על השלט של המזגן)
[…] הבייט הלבן מפרסם מדריך מפורט לעבודה עם ארדואינו. הפרוייקט הלימודי כולל עבודה עם חיישן טמפרטורה חיצוני […]
טוב לשמוע. ואגב – אם תגיע לטפל בעניני array (והרי אין אופציה לא לטפל בזה) אשמח אם תוכל להקדיש זמן לטיפול מורכב יותר בהם – מעבר לדוגמאות סטייל Knight Rider" example" וכיוב'. טיפול מאסיבי יותר שחסר גם באתרים לועזיים…
סתם, בקשה… 😉
אתה מתכוון למשהו כזה?
http://www.youtube.com/watch?v=WKE26TWLdaI
וואו, מוצלח ביותר. האמת שכוונתי הייתה ליכולת ליצור array עם גודל משתנה בעקבות טריגר חיצוני, ואז מניפולציות שונות על אותו array.
למשל קוד שלוכד תנועה של פוטנציומטר מטריגר אחד ("rec") ועד טריגר שני ("stop") – מה שמחייב שהarray בכל פעם מכיל מספר אלמנטים שונה, ואז מניפולציות על האלמנטים (קדימה, אחורה, ממוצע, smoothing, חילוק לקבוצות על פי גדלים ועוד ועוד).
אה, malloc, פוינטרים וכאלה… 🙂
בהחלט נושא ראוי, אבל אני אזהיר מראש: כשיש לך רק 2 קילובייט של זכרון דינמי, זה מציב מגבלות חמורות מאד על הקצאות זיכרון לפי דרישה. ממוצע רגיל אפשר, למשל, לחשב על מדידות בלי שום מערך; אבל אם אתה ממש רוצה היסטוריה, כדאי שתתחיל לחשוב כבר עכשיו על רכיבי זכרון חיצוניים.
בדיוק כאלה!
כן, אני מודע למגבלות ולאפשרות להרכיב שילד SD כדי לרשום היסטוריה רצינית, אבל arrays עם unsigned int אני מניח שאפשר למעלה מ1000 גם, וזה מספיק לי לעת עתה. כמובן שעם האוכל בא התיאבון
אני מנסה עכשיו למצוא פיתרון להחלקה של curve של ערכים, ממינימום למקסימום, כדי להפטר מרעשי פוטנציומטר מיותרים.
ושוב – כמה טוב שיש מקום ישראלי לשוחח בו על דברים כאלו!
הי – תודה רבה על הדיל המצויין ובדיוק כשחיפשתי נאנו. (אני מקווה שהוא בנוי כראוי – אעדכן…) 🙂
בכיף. זה אתר מדהים למי שמוכן לחכות כמה שבועות למשלוח שיגיע. עד עכשיו הייתי מרוצה מהם מאד, כולל שירות הלקוחות.