יום שני, 7 ביוני 2010

זמני השהייה ושקט שקט שקט

בעיה שהתעוררה במהלך העבודה הייתה שהשירים התחילו ונגמרו בדיוק על המילישנייה. מה שגרם אי נחת לקוד אשר סובל מתוספות של זמני השהייה ושאר עיכובים כך שלכל זמן שבו שיר מתנגנן יש ספיחים בצורה של זמני השהייה נוספים. הזמנים האלו מצטברים וקשה לפצות עליהם במסגרת הטכנית של הפרוייקט הנוכחי (יש להשתמש בצ'יפ ISD4004 שהוא צ'יפ סאונד עם פנייה ישירה לזיכרון), אבל במסגרת הפרוייקט מצאנו פתרון קלאסי ונחמד, הוספנו זמן השהייה משלנו בסוף כל שיר, כך שיש מרווח בטחון של שקט בסוף כל שיר ואז ההשהייות המצטברות נכנסות בחישוב בתוך הזמן הפנוי שנשאר כך אין מצב של חריגה לשיר אחר ברשימה ובכך שינוי סדר השמעת השירים בעיה שליוותה אותנו לא מעט זמן ונפתרה בסופו של דבר.


לוגיקה כללית ותנאים סבוכים

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

התנאים:

1. מישהו עובר ליד הפח -> תוצאה -> השיר: לתת
2. מישהו עובר ליד הפח אחרי זמן קצוב (30 שניות) -> השיר: בדד
3. מישהו זורק לפח אשפה -> השיר: תודה 
4. מישהו זורק לפח אשפה אחרי זמן קצוב (30 שניות) -> השיר: אש
5. מישהו דוחף את הפח או מזיז אותו מהמקום -> השיר זה הזמן לסלוח.

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

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

מערכת התנאים המורכבת לקרבה+זריקה:

כאשר:

dist הוא הערך שמתקבל מחיישן הקרבה
trash הוא הערך שמתקבל מחיישן האור (כניסת זבל לפח)
big time הוא הזמן מרגע הפעלת הפח
last_dist_time ו last_in_time הם הזמנים שנספרים מרגע הפעולות של זריקה או התקרבות.

התנאי:
if  (dist<20 || dist1<20)
{
          if (trash==0)
            {
                digitalWrite(inled,HIGH);
                if((big_time - last_in_time) / 1000 > 30 && last_in_time!=0) {
                    gotoTrack(4);
                    pp();delay(23000);pp();
                   last_in_time = big_time;
                } else if((big_time - last_in_time) / 1000 <30) {
                    gotoTrack(3);
                    pp();delay(16500);pp();
                    last_in_time = big_time;
               }
               } else {
     digitalWrite(inled,LOW);
    digitalWrite(distled,HIGH);
    if((big_time - last_dist_time) / 1000 >30 && last_dist_time!=0) {
        gotoTrack(2);
        pp();delay(13000);pp();
        last_dist_time = big_time;
        } else  if((big_time - last_dist_time) / 1000 <30){
          gotoTrack(1);
        pp();delay(16000);pp();
        last_dist_time = big_time;
        }
     
}
if (dist>20 || dist1>20)
{
digitalWrite(distled,LOW);
}
}

פונקציות! פונקציות! פונקציות!

 פונקציית נגן/הרץ קדימה

על מנת להפעיל את נגן המפ3 שחיברנו אל המיקרומעבד, השתמשנו במצמדים פוטואלקטרים 4N27 היחידה מקבלת את האות הדיגיטלי כפי שהוא יוצא מהמיקרומעבד והתזמונים הם קריטים בהפעלת המפסק כי הם צריכים לדמות לחיצה אנושית אך עדיין שתהיה נכונה באופן עקבי (אחרי בדיקות רבות וניסויים רבים ובעזרתו של עמיר הגענו לתזמון של 80/40 מילישניות בהתאמה לזמן כבוי/דלוק) בקוד כתבתי פונקציה שמתאימה ללחיצה על נגן.

void pp()
{
digitalWrite(playpin,HIGH);
delay(80);
digitalWrite(playpin,LOW);
delay(40);
}
פונקציית העברת שיר באופן יחסי

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

לדוגמא: 

יש 5 שירים סך הכל ברשימה.
אנחנו נמצאים בשיר מס 3 ורוצים להגיע לשיר מס' 3 - נצטרך לעבור 5 שירים שירים
אנחנו נמצאים בשיר מס 3 ורוצים להגיע לשיר מס' 2 - נצטרך לעבור 4 שירים קדימה
אנחנו נמצאים בשיר מס 3 ורוצים להגיע לשיר מס' 1 - נצטרך לעבור 3 שירים קדימה

וכיו"ב בהתאמה.

כך שהפונקציה תהיה:

void gotoTrack(int trackNo) {
 if(trackNo > currentTrack) {
   skipForward(trackNo - currentTrack);
}
 else if(trackNo < currentTrack) {   
   skipForward(totalTrackCount - currentTrack + trackNo);
} else {
  skipForward(totalTrackCount);
}
 currentTrack = trackNo;
}
החלק הראשון והשני של התנאי בודק את המיקום ביחס לשיר הנוכחי והתנאי האחרון בודק אם זהו אותו שיר, בסוף הפונקציה יש עדכון של מס השיר לנתון שמכיל את מספר השיר הנוכחי.

פונקציית בדיקת לדים - הפעלה ראשונית

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

הפונקציה:


void blip()
{
for(int i=0; i<5; i++){
digitalWrite(inled,LOW);
digitalWrite(distled,HIGH);
delay(100);
digitalWrite(distled,LOW);
digitalWrite(posled,HIGH);
delay(100);
digitalWrite(inled,HIGH);
digitalWrite(posled,LOW);
delay(100);
}
digitalWrite(posled,LOW);
digitalWrite(inled,LOW);
digitalWrite(distled,LOW);
}