זיכרון של מחשבים, ושל מיקרו-בקרים, הוא למעשה רצף אחד ארוך של ביטים: "תאים" זעירים שכל אחד מהם יכול להיות באחד משני מצבים מוגדרים מראש (מצבים אותם אנחנו מכנים "0" ו-"1"). כל משתנה, כל ערך שאנחנו מציינים בתוכנה שלנו הוא בסופו של דבר קטע קצר על פני הרצף הזה. רוב שפות התכנות המודרניות עושות מאמצים להסתיר את העובדה הזאת מאיתנו, וזה בסדר גמור – אבל לא כשאנחנו עובדים עם מיקרו-בקרים. מגבלות החומרה והארגון הפנימי של המיקרו-בקר מחייבים כל מתכנת ראוי לשמו לעבוד גם ברמת הביטים, וזהו הנושא שנתחיל לכסות בפוסט הנוכחי.
נושא הביטים מתחלק לשני תת-נושאים עיקריים: ייצוג בינארי, ולוגיקה בוליאנית שבה נעסוק בפוסט הבא. שניהם טכניים למדי ועשויים להיראות לכם יבשים. אף על פי כן, מבין כל הפוסטים בסדרת "שפת C למתחילים", שניים אלה הם כנראה הפוסטים הכי קריטיים. אתם חייבים להבין כל מה שכתוב בהם בצורה מושלמת, ולהיות מסוגלים לחזור על זה גם אם יעירו אתכם באמצע הלילה. בלי המידע הזה לעולם לא תוכלו לתכנת מיקרו-בקרים. הדגשתי מספיק מילים? המסר עבר? אז קדימה, לעבודה…
תחום ה-RF (ראשי תיבות של Radio Frequency – תדר רדיו, כשהכוונה בדרך כלל לתקשורת אלחוטית באמצעות גלי רדיו) הוא תחום מסובך. לא שכל תחומי האלקטרוניקה האחרים הם טיול בשכונה, כמו שאומרים – ואף על פי כן, הסביבה הפיזית שלנו רוויה בכל כך הרבה הפרעות ומכשולים לגלי רדיו, שנדרש מאמץ רציני כדי לשלוח ולקלוט מידע בעזרתם ללא שגיאות ובקצב סביר.
מבחר התקני ה-RF שעומדים לרשותנו (חובבי הארדואינו) גדול, וגם הביקוש להם גדול: זו הדרך הפרקטית היחידה שלנו לשלוח מידע, למשל, מחדר לחדר בבית. עם זאת, היעילות והטווח של ההתקנים הללו תלויה בעוצמה ובתחכום של מעגלי העיבוד שלהם, וזה מתבטא במחיר. קחו לדוגמה את הקיטים הבסיסיים של RF, צמד משדר+מקלט שאפשר להשיג תמורת חמישה-שישה דולרים בלבד. לכאורה עסקה מצוינת, אבל מי שינסה לעבוד איתם בצורתם הגולמית (כפי שעשיתי במחסום הצעצוע) יגלה במהרה שאפילו משימה צנועה כמו זיהוי של אות פשוט ("יש/אין") היא קריעת ים סוף. האם נגזר עלינו לוותר על RF, או לחלופין להיפרד מעשרות רבות של דולרים עבור התקני Zigbee, בלוטות' ודומיהם?
בדוגמאות הקוד בפוסט הקודם בסדרה נתתי ערכים למשתנים, וגם שיניתי את הערכים הללו, בעזרת ביטויים כמו-
x = 1;
x = x + 2;
הביטויים האלה נראים כל-כך מובנים מאליהם, שאף אחד לא תהה מה בעצם קורה שם; אך מאחורי הקלעים של הקוד הזה עומד מנגנון מתוחכם ורב-עוצמה, שמהווה את אחת מאבני היסוד של התכנות בכלל – וגם מאפשר לנו, ספציפית בשפת C, לבצע טריקים שימושיים מאד ואפילו מרהיבים מכל מיני סוגים. בפוסט הנוכחי נגרד את קצה הקרחון של המנגנון הזה, וגם נפתור את התעלומה כמה זה x = 3. מוכנים?
אלה מכם שקראו את הטור שלי בנענע10, "לפרק את הבייט", אולי יזכרו את האייטם הזה. לאחרים ולמי ששכח, אני מציג שוב את ideone – אתר שמאפשר לכם לתכנת בכל אחת מעשרות שפות תכנות שונות ישירות בדפדפן, בלי להתקין שום דבר על המחשב האישי. הקלט והפלט הם, כמובן, טקסטואליים בלבד והכי בסיסיים שאפשר, אך זהו עדיין כלי מעולה ללמידה. עם התאמות ספורות של הקוד, תוכלו להשתמש ב-ideone גם כדי ללמוד את שפת C לתכנות מיקרו-בקרים. מומלץ לפתוח שם חשבון, כדי שתוכלו לשמור קטעי קוד לשימוש חוזר.
אם יהיה ביקוש (בתגובות), אציג מדריך מפורט לשימוש באתר הזה, אם כי אני סבור שעם קצת משחק והתנסות תוכלו לגלות את כל התכונות החשובות לבד.
והערה אדמיניסטרטיבית: התקנתי בבלוג תוסף שאמור לאפשר לכם לקבל עדכונים במייל על תגובות חדשות, תגובות לתגובות שלכם וכאלה. תרגמתי את הטקסטים של התוסף לעברית בעצמי, ועדיין לא בדקתי אותו ביסודיות. אתם מוזמנים לנסות ולספר לי איך זה הולך!
בואו נסתכל על התוכנית הכי פשוטה ובסיסית שאפשר להעלות ללוח ארדואינו מסביבת הפיתוח שלו:
void setup() {
}
void loop() {
}
מה שיש לנו כאן זה בעצם הגדרה של שתי פונקציות, אחת בשם setup ואחת בשם loop. בהמשך, כשאדבר על פונקציות, אסביר את המשמעות של המילה void ואת הסוגריים הרגילים. בינתיים, נתמקד בסוגריים המסולסלים – } ו-{. בשפת C, סוגריים מסולסלים יוצרים "בלוק" של קוד, מבנה שמכיל פקודות. כמו שאפשר לראות בתוכנית למעלה, המבנה הזה יכול להיות ריק לגמרי. כמו כן, בלוק קוד יכול להכיל בלוקים אחרים, מה שאומר שהתוכנית הבאה לגיטימית לגמרי – אפילו שהיא מטופשת לחלוטין…
מכיוון שכבר היה לי ביד ג'וק ATMega328-PU חופשי עם Bootloader של ארדואינו, החלטתי ללכת עד הסוף ולהרכיב אותו על מטריצה, כפי שמתואר כאן. העברה של מיקרו-בקר מלוח הארדואינו למטריצה היא שלב נוסף בדרך ל"עצמאות" – שחרור מהסטנדרטים והמגבלות של עולם הארדואינו ומעבר לתכנון מעגלים יעודיים, בהתאמה מדויקת לצרכים הספציפיים של כל פרויקט. שלא יהיה ספק, הארדואינו הוא דבר מדהים ואפשר לעשות איתו אינספור דברים מדהימים לא פחות גם במסגרת המגבלות הקיימות – ובכל זאת, גם בקטע של עלויות וגם בקטע של למידה, אף פעם לא מזיק לפתוח את הראש גם לכיוונים אחרים. אז הנה לפניכם ההתרשמות שלי מההרכבה הזו – מיד אחרי התמונה.
אחרי שהוצאתי מהקופסה את הרדיו-דיסק הפשוט שקניתי לילדים, הבחנתי בין חומרי האריזה בשני קלקרים לא-שגרתיים: מעין צלחות עגולות עם שוליים ישרים וגבוהים, וארבעה חריצים רחבים על ההיקף. הקלקרים האלה פשוט התחננו לגורל מעניין יותר מאשר פח הזבל – ואחרי שתפסו מקום על המדף כמה ימים הבנתי פתאום מה אפשר לעשות איתם: רמקול לסלי!
שפת התכנות C היא כלי העבודה הנפוץ והשימושי ביותר לתכנות של מיקרו-בקרים. למען הסר ספק, לא חסרים פתרונות אחרים – מאסמבלי ועד בייסיק וג'אווה – אך מי שרוצה לעבוד עם טווח רחב ככל האפשר של מיקרו-בקרים, ולהוציא מהם את המקסימום בלי להסתבך עד מעל הראש בפרטים לא-רלוונטיים, חייב לדעת C – ולדעת אותה טוב.
סדרת פוסטים זו מיועדת לחובבים שרוצים להכיר, או להכיר טוב יותר, את שפת C לצורך תכנות מיקרו-בקרים וארדואינו בפרט. אנחנו נתחיל מההתחלה ממש, לטובת מי שטרם כתב ולו שורת קוד אחת, ונתקדם לאט ובסבלנות לעבר מאפיינים וטכניקות מורכבים יותר. הרעיון פה הוא לא "ללמוד לתכנת ב-C" – יש בערך מאה מיליון ספרים ומדריכים אחרים שעושים את זה, וחלק ממה שהם מלמדים לא רלוונטי לענייננו – אלא לתת את הבסיס החיוני, ואז להיחשף לאותם אלמנטים של השפה ולאותן טכניקות שיעזרו לנו לתכנת טוב יותר את הארדואינו שלנו.
איך גורמים לארדואינו (או לכל מיקרו-בקר, לצורך העניין) לבצע יותר מפעולה אחת בו-זמנית? למשל, איך עושים שהארדואינו גם יהבהב בנורית LED בקצב קבוע, גם יקרא נתונים בזמן אמת מחיישן מרחק וגם יגיב להם בשינוי צליל ברמקול בלי שהפעולות יפריעו זו לזו?
בתור מי שתכנת עוד בימי DOS העליזים, התשובה היתה לי כל כך מובנת מאליה, שלא שמתי לב בכלל שיש כאן שאלה. אך מכיוון שהנושא עלה באופן בלתי-תלוי מספר פעמים, ברור שזה לא באמת מובן מאליו – והפוסט הנוכחי נועד להסיר את הערפל מהעניין הבסיסי-אך-מסתורי הזה.
לוח הארדואינו הכחול (בדרך כלל) איתו אנו עובדים הוא, ברובו המכריע, רק ציוד היקפי עבור הרכיב החשוב באמת: המיקרו-בקר, הלא הוא הג'וק מרובה הרגליים ששוכן בלב הלוח ומנהל את הכל. את הג'וק הזה אפשר להחליף אם הוא נשרף, ואפשר גם לשלוף אותו מהארדואינו האהוב והמוכר ולשתול אותו במעגל אחר לגמרי, בו יעבוד כמיקרו-בקר ייעודי.
היום הגיעו אליי שני הג'וקים שמימין בתמונה – מסוג ATMega328-PU בתצורת DIP (זו עם הרגליים הארוכות שאפשר לדחוף לתוך מטריצה). אלו הם מיקרו-בקרים מאותה משפחה שמשמשת בארדואינו Uno ו-Duemilanove, ובעיקרון אפשר להחליף בעזרתם את הג'וק שהגיע עם הארדואינו. אבל כדי לגרום לזה לעבוד, צריך היה לבצע עוד שלב בדרך: צריבה של Bootloader. מה זה Bootloader ואיך צורבים אותו?