16 בפברואר 2024

אגרת לבעלי קופת צדקה - זורע צדקות


עבור מחזיקי קופת הצדקה "זורע צדקות" היקרים וכלל ישראל באשר הם: הפסוק מספר ישעיה על תמונת  הAI שיצרתי עם DALL•E, מבטאת רעיון קבלי עמוק: יש מצוות מעטות ובינהן מצוות הצדקה / גמילות חסדים שיש מהן שכר בעולם הזה (והקרן קיימת לעולם הבא). השכר הוא המשכה מאור אינסוף שלא יכול להתלבש בעולם הזה באופן ישיר ולכן הוא "זולג" מנקבים, כמו נקבי השריון. אבל ששפע מאור אין סוף זולג לעולם הזה. הצד האחר/סטרא אחרא, יכול לינוק מהשפע הזה ולכן מתבצעת גם פעולה הפוכה של סתימת הנקבים מאור מקיף, כדי להגן מהזליגה הזאת  וזה המשל של קשקשים על שריון וכשם שבשריון מצטרפת כל קליפה וקליפה לשריון גדול, כך בצדקה מצטרפת כל פרוטה ופרוטה לחשבון גדול. כי זהו גדלותו של הבורא להעניק שפע ולהגן על מקבל השפע. יברכך ה' ו ישמרך. לכן יש חשיבות בנתינת צדקה מתמשכת ולא חד פעמית, כדי שנבנה סביבנו את השריון הרוחני. 💫.שבת שלום ושנזכה שה"קרן", עצם השכר, יתגלה כאן למטה לעתיד לבא בגאולה האמיתית והשלמה תכף ומיד ממש.

13 בפברואר 2024

משלוח מנות PurimIrisBox

 

תקציר

PurimIrisBox הוא משלוח מנות ייחודי בהשראת סדרת הטלבזיה Stargate, אשר המוטיב המרכזי בו היה IrisDoor המאפשר שער גישה בין נקודות שונות בחלל 🌠

כדי לפתוח את משלוח המנות (או כדי להגיע ל-"אוצר" 😁), ישנם שני מסלולים, כאשר הראשון מבין השניים הוא המומלץ:

הראשון

פתרון חידת הגיון (פתרון מילולי המורכב ממילה אחת או יותר).

עברית

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

English

In a garden rich with history's tales, a unique flower unfurls its vibrant veils. Thirteen petals it proudly displays, together mirroring the Thirteen Attributes of Mercy, divine rays. More than a mere bloom in history's embrace, it bears a name echoing through time and space. Named for a patriarch, a beacon for a nation, symbolising a people's enduring foundation. In the darkest hour, it became a light so stark, turning night to day, sorrow to an arc of joy. What is this flower, a symbol so brave, named for the one who struggled and hope to many gave?


הוראות הפעלה *

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

השני

פתיחה רגילה של המשלוח - לחיצה על הכפתור - פתרון ל"חלשים"!

לקריאה נוספת על משמעות הפתרון

לא להציץ לפני שפותרים! 🙂








תאור הפרוייקט



חלקים עיקריים:
  • גוף המשלוח
  • בסיס הכולל מעבד Pi Zero W, מיקרופון וחיווט 
  • מכסה Iris הנשלט ע"י מנוע סרוו

עיצוב





בניה

IrisCover







לפני הצביעה, חובה למלא ב- Sealer




חיבור מיקרופון הUSB

חיווט מקור מטח חיצוני


חיבור Servo, Led and Switch 



רכיבים

NumberDescMaterial#
1Cover 2 colorABSBlack/Green1
2Cover HolderABS/PLABlack3
3Small Cog coverABS/PLABlack1
4Big CogPETGOrange1
5Small CogPETGOrange1
6FinABSOrange5
7Big Cog BaseABSOrange/Black1
8BodyABS/PLAGreen/White1
9Base CoverPLABlack1
10Base BodyPLABlack1
11USB HolderPLABlack1
12Servo CoverABSWhite1
12Push Button1
13PI Zero1
14Neo pixel1
15Mini Servo SG901
16USB Type A to micro USB1
17Microphone1
18Micro USB female1
19M3*10mm nut6
20BreadBoard wires10
215V 3 wire junction1
22Spacer 2.5mmx0.5cm4
232.5mm plastic nut1
243 sec glue1
25Epoxy Glue1
26Gear lubricant1
27DecoArt Sealer/Finisher DAS13 Matte1
28Black Marker ProMaker XB Black1
29Micro SD Card 32G1


חיווט


קוד

סקריפט ראשי - קישור
שרת מנוע סרוו ולד - קישור
אפליקציה ראשית, זיהוי דיבור- קישור 


קרדיט: Rocco's Stuff שממנו קיבלנו השראה לעיצוב. הדיזיין המקורי הופץ תחת רשיון CC BY-NC-SA


עיצוב סכמתי. תוכנה ותכנון אפליקטיבי: אסף מתן






עיצוב פרטני: בועז מתן






סיכום

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

מי שדם דומה זורם בעורקיו, מוזמן ליצור קשר asaf.matan@gmail.com או בתגובות למטה.


רשיון



The license code "CC BY-NC-ND" refers to one of the Creative Commons licenses, specifically:


CC (Creative Commons): This is the organization that offers various standardized licenses to enable content creators to share their work with specific conditions.


BY (Attribution): This element requires that the original creator must be credited whenever the work is used or shared. The user must acknowledge the authorship in a manner specified by the creator or licensor.


NC (Non-Commercial): The work can be used and shared, but only for non-commercial purposes. This means it cannot be used in ways that are primarily intended for or directed toward commercial advantage or monetary compensation.


ND (No Derivatives): The work can be shared, but it must remain unchanged and whole, meaning no derivatives or adaptations of the work are allowed. This means you cannot edit, alter, or build upon the work in any way.






9 בדצמבר 2023

קופת צדקה זורע צדקות - Charity Sower

 

מבוא

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

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

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

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

הביטוי "זורע צדקות"

"זוֹרֵעַ צְדָקוֹת. מַצְמִיחַ יְשׁוּעוֹת" (סידור התפילה).

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

בנוסף, על בסיס הפסוק :
"וילבש צדקה כשריון וכובע ישועה בראשו"(ישעיה נ"ט).

מסביר האדמו"ר הזקן - "ודרשו רז"ל מה שריון זה כל קליפה וקליפה מצטרפת לשריון גדול אף צדקה כל פרוטה ופרוטה מצטרפת לחשבון גדול".

בהשראת המקורות הנ"ל עיצבנו* קופת צדקה חדשנית שמאפשרת שימוש חוזר במטבעות (שקשה יותר ויותר להשיג בימים אלה) כדי:
1. לאפשר תרומה יום יומית של מטבעות בתפילה 
2. למנוע את הצורך לחפש כל פעם מטבעות מחדש

* אסף מתן - עיצוב סכמתי,  בועז מתן - עיצוב פרטני





קופת צדקה - זורע צדקות









תאי אחסון

תא תרומה - התא בו תורמים במהלך התפילה (לפני הודו/ב"ויברך דוד")
תא אחסון מטבעות - משמש לאחסון מספר קבוע של מטבעות. מתא אחסון זה לוקחים מטבעות בזמן התפילה ותורמים בתא הימני - "תא התרומה" 
תא אחסון שטרות - בתא זה ניתן לאחסן שטרות כסף בשווי הכולל של "תא אחסון המטבעות"

אופן השימוש

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

באופן זה לעולם לא "תתקע" בלי בטבעות לתרומה.

תמונות נוספות


מודל 3 תאים




מודל 2 תאים




אריזה

מילות סיכום

שמחתי מאד לבצע את הפרוייקט בשיתוף עם אחי בועז מתן. יהיו אולי כאלו שיתהו על השילוב של רוחניות וטכנולוגיה, אבל זה חלק ממי שאני. אני להוט להתחבר, לשתף ולדון עם אחרים שחולקים נקודות מבט דומות.
ניתן ליצור קשר בתגובות וכן בקישור הזה: http://linktr.ee/asafmatan

רשיון





The license code "CC BY-NC-ND" refers to one of the Creative Commons licenses, specifically:

CC (Creative Commons): This is the organization that offers various standardized licenses to enable content creators to share their work with specific conditions.


BY (Attribution): This element requires that the original creator must be credited whenever the work is used or shared. The user must acknowledge the authorship in a manner specified by the creator or licensor.


NC (Non-Commercial): The work can be used and shared, but only for non-commercial purposes. This means it cannot be used in ways that are primarily intended for or directed toward commercial advantage or monetary compensation.


ND (No Derivatives): The work can be shared, but it must remain unchanged and whole, meaning no derivatives or adaptations of the work are allowed. This means you cannot edit, alter, or build upon the work in any way.









20 באפריל 2023

"זורע צדקות" - "Charity Sower" - אביב 2023

תקציר

"זוֹרֵעַ צְדָקוֹת. מַצְמִיחַ יְשׁוּעוֹת" (סידור התפילה).

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

בנוסף, על בסיס הפסוק :
"וילבש צדקה כשריון וכובע ישועה בראשו"(ישעיה נ"ט).

מסביר האדמו"ר הזקן - "ודרשו רז"ל מה שריון זה כל קליפה וקליפה מצטרפת לשריון גדול אף צדקה כל פרוטה ופרוטה מצטרפת לחשבון גדול".

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




תאור הפרוייקט

תאור מפורט של הפרוייקט ורשימת רכיבים, כלים, תוכנות וקישורים, ניתן למצוא כאן:

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

התכנון מבוסס על מערכת מוכללת של חברת Seeed בשם Wio Terminal.

מדריך מעולה על הפלטפורמה:

Wio Terminal כולל רכיבים רבים בנוסף למעבד SAMD51, ובינהם שני שקעי Grove לחיבור התקנים פריפריאליים סטנדרטיים של חברת Seeed וכן התקנים המתבססים על תקשורת I2C של חברות אחרות כמו חיישן המרחק של חברת Adafruit. בפרוייקט זה השתמשתי בשני רכיבים פריפראיליים:
1. GPS Air 530 - לשם איתור מקום התרומה
2. חיישן מרחק VCNL4040 - זיהוי של הכנסת מטבע לקופה

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

כפי שניתן לראות בתרשים הזרימה בהמשך, ישנם שני אופציות הפעלה. עם חיבור Wifi וללא. כאשר לוחצים על ה-Joystick בקדמת המסך תוך כדי הפעלת המחשב, מתבצע חיבור לרשת הWifi. חיבור לאינטרנט נדרש רק כאשר רוצים לשדר את כל הקורדינטות שנאספו עד כה לשירות הענן Wappsto, שמראה בצורה וזואלית באיזה מקום נתרם הכסף. כדי לשדר את כל הקורדינטות שנאספו לWappsto יש ללחוץ על כפתור B (הכפתור האמצעי מעל wio terminal) כאשר המחשב נמצא במוד Wifi.

מידע נוסף ורלוונטי על שלבי החיבור של Wio Terminal לשרות הענן Wappsto:

כאשר המחשב מאותחל בצורה רגילה. הWifi כבוי, חיישני הGPS והמרחק פועלים וניתן לראות את הקורדינטות המיקום הנוכחיות במסך אחד, ובמסך השני ניתן לראות כמה מטבעות נתרמו. כדי לדפדף בין המסכים לוחצים על כפתור C, השמאלי. מעל Wio Terminal

פרוייקט שהתבססתי עליו עבור קריאת נתוני הGPS:

תרשים זרימה:


תרשים זרימה


רכיבים

  • Seeed Wio Terminal Main controller
  • Seeed GPS Module Air 530
  • חיישן מרחק VCNL4040 של חברת Adafruit
  • כבל USB Type A- TypeC עם מחבר זוויתי
כאמור, קישורים לחלקים מופיעים בפרסום באתר Hackster בקישור למעלה.

הדפסות תלת מימד והרכבה

זורע צדקות - עיצוב כללי 



פאנל קדמי



חלקים מודפסים לפני הרכבה



הרכבת התקני הנעילה

תא צדדי שמכיל מטבעות שלא נתרמו




תא צדדי ותא ראשי

חומרה, חיווט ותוכנה

שלושת רכיבי החומרה:

Wio Terminal - Picture from Seeed website


Air 530 GPS module - Picture from Seeed website



VCNL4040 - Picture from Adafruit website


חיווט חשמלי


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


דיאגרמת חיבורים




חיבור התומכים ל Wio Terminal




הרכבת הGPS וחיישן המרחק בתא במרכזי



בדיקה ראשונית של מסך הGPS




מסך מונה המטבעות





מסך הפתיחה




מוכנים לנסיעה (בטיחותית) של "זריעת צדקות"



ציון מקומות התרומה לאחר העלאת הקורדינטות לאתר Wappsto


קוד המקור


// Written by Asaf Matan
// GPS code is based on
// https://www.hackster.io/SeeedStudio/wio-terminal-gps-ad70e2 Arduino/Wappsto
// example
#include <Adafruit_VCNL4040.h>
#include <SPI.h>
#include "TFT_eSPI.h"
#include <Seeed_FS.h>
#include <SoftwareSerial.h>
#include <TinyGPS++.h>
#include <WiFiClientSecure.h>
#include <WiFiMulti.h>
#include "Free_Fonts.h"
#include "RawImage.h"
#include "SD/Seeed_SD.h"
#include "Wappsto.h"
#include "WappstoValueTypes.h"
#include "wappsto_config.h"
#include "my_secrets.h"
WiFiMulti wifiMulti;
WiFiClientSecure client;
Wappsto wappsto(&client);
#define BUZZER_PIN WIO_BUZZER
Network *myNetwork;
Device *myDevice;
Value *myLatitudeValue;
Value *myLongitudeValue;
DeviceDescription_t myDeviceDescription = {
.name = "Location Device1",
.product = "",
.manufacturer = "",
.description =
"Example sending location shown on map in the Wappsto dashboard",
.version = "1.0",
.serial = "00001",
.protocol = "Json-RPC",
.communication = "WiFi",
};
double myLatitude = MY_LAT;
double myLongitude = MY_LON;
void updateLocation(double valLatitude, double valLongitude) {
myLatitudeValue->report(valLatitude);
myLongitudeValue->report(valLongitude);
}
void refreshLocationCallback(Value *value) {
// Nothing to read from wappsto no nothing to refresh
}
bool skip_wifi = false;
const char *ssid = MY_SSID;
const char *password = MY_PASS;
Adafruit_VCNL4040 vcnl4040 = Adafruit_VCNL4040();
SoftwareSerial mySerial(0, 1); // RX, TX
TinyGPSPlus gps;
TFT_eSPI tft;
TinyGPSCustom ExtLat(gps, "GPGGA", 3); // N for Latitude
TinyGPSCustom ExtLng(gps, "GPGGA", 5); // E for Longitude
const float pi = 3.1415;
int menu = 0, p_menu = 3;
int logging = 0, sat_n = 0;
int coin_counter = 0;
int wappsto_transmited_lines = 0;
String F_name = "db.txt";
String p_hour, p_lat, p_lng, p_alt, p_sat, p_date;
String p_coin_counter;
// for Satellites position
static const int MAX_SATELLITES = 40;
TinyGPSCustom totalGPGSVMessages(gps, "GPGSV",
1); // $GPGSV sentence, first element
TinyGPSCustom messageNumber(gps, "GPGSV",
2); // $GPGSV sentence, second element
TinyGPSCustom satsInView(gps, "GPGSV", 3); // $GPGSV sentence, third element
TinyGPSCustom satNumber[4]; // to be initialized later
TinyGPSCustom elevation[4];
TinyGPSCustom azimuth[4];
TinyGPSCustom snr[4];
struct {
bool active;
int elevation;
int azimuth;
int snr;
int dsp;
} sats[MAX_SATELLITES];
String N_date, hour0;
bool sd;
String lat0, lng0;
void disp_title() {
if (menu == 0) {
tft.setFreeFont(FF0);
tft.fillScreen(TFT_BLACK);
tft.setTextSize(3);
tft.drawString("GPS", 120, 3);
tft.setTextSize(2);
tft.drawString("Date", 30, 42);
tft.drawString("Time", 30, 74);
tft.drawString("LAT", 30, 106);
tft.drawString("LONG", 30, 138);
tft.drawString("ALT", 30, 170);
tft.drawString("Satellites", 30, 202);
if (sd != true) {
tft.drawChar(295, 223, 'S', TFT_WHITE, TFT_RED, 2);
tft.drawChar(307, 223, 'D', TFT_WHITE, TFT_RED, 2);
}
p_hour = " ";
p_lat = " ";
p_lng = " ";
p_alt = " ";
p_sat = " ";
p_date = " ";
} else if (menu == 1) {
tft.setFreeFont(FF0);
tft.fillScreen(TFT_BLACK);
tft.setTextSize(3);
tft.drawString("Stats", 120, 3);
tft.setTextSize(2);
tft.drawString("Coins", 30, 42);
p_coin_counter = " ";
}
}
String doubleToString(double value, int precision) {
char buffer[20];
dtostrf(value, 0, precision, buffer);
return String(buffer);
}
void displayInfo() {
if (gps.location.isValid()) {
lat0 = doubleToString(gps.location.lat(), 6);
lng0 = doubleToString(gps.location.lng(), 6);
} else {
lat0 = "0";
lng0 = "0";
}
if (gps.date.isValid()) {
N_date = String(gps.date.day()) + "/" + String(gps.date.month()) + "/" +
String(gps.date.year());
} else {
N_date = "00/00/0000";
}
if (gps.time.isValid()) {
hour0 = "";
if (gps.time.hour() < 10) hour0 = "0";
hour0 += gps.time.hour();
hour0 += ":";
if (gps.time.minute() < 10) hour0 += "0";
hour0 += gps.time.minute();
hour0 += ":";
if (gps.time.second() < 10) hour0 += "0";
hour0 += gps.time.second();
} else {
hour0 = "00:00:00";
}
}
void displayInfoData(void) {
if (menu == 0) { // menu 0
if (menu != p_menu) {
disp_title();
p_menu = menu;
}
if (N_date != p_date) { // Date
tft.fillRect(100, 42, 120, 16, TFT_BLACK);
tft.drawString(N_date, 100, 42);
p_date = N_date;
}
if (hour0 != p_hour) { // Time
tft.fillRect(100, 74, 120, 16, TFT_BLACK);
tft.drawString(hour0, 100, 74);
p_hour = hour0;
}
if (lat0 != p_lat) { // Latitude
tft.fillRect(100, 106, 132, 16, TFT_BLACK);
tft.drawString(lat0, 100, 106);
p_lat = lat0;
}
if (lng0 != p_lng) { // Longitude
tft.fillRect(100, 138, 156, 16, TFT_BLACK);
tft.drawString(lng0, 100, 138);
p_lng = lng0;
}
if (String(gps.altitude.meters()) != p_alt) { // Altimeter
tft.fillRect(100, 170, 60, 16, TFT_BLACK);
tft.drawString(String(gps.altitude.meters()), 100, 170);
p_alt = String(gps.altitude.meters());
}
if (String(gps.satellites.value()) != p_sat) { // N of Satellites
tft.fillRect(160, 202, 32, 16, TFT_BLACK);
tft.drawString(String(gps.satellites.value()), 160, 202);
p_sat = String(gps.satellites.value());
}
} // end of menu=0
else if (menu == 1) {
if (menu != p_menu) {
disp_title();
p_menu = menu;
}
if (String(coin_counter) != p_coin_counter) { // Coin Counter
tft.fillRect(100, 42, 120, 16, TFT_BLACK);
tft.drawString(String(coin_counter), 100, 42);
p_coin_counter = String(coin_counter);
}
}
}
void playTone(int tone, int duration) {
for (long i = 0; i < duration * 1000L; i += tone * 2) {
digitalWrite(BUZZER_PIN, HIGH);
delayMicroseconds(tone);
digitalWrite(BUZZER_PIN, LOW);
delayMicroseconds(tone);
}
}
void writeIntToSD(const char *filename, int value) {
File file = SD.open(filename, FILE_WRITE);
if (file) {
file.print(value);
file.close();
} else {
Serial.println("Error writing to file");
}
}
int readIntFromSD(const char *filename) {
File file = SD.open(filename, FILE_READ);
int value = 0;
if (file) {
value = file.parseInt();
file.close();
} else {
Serial.println("Error reading from file");
}
return value;
}
String *parseCSV(String data, int &fieldCount) {
String *fields =
new String[data.length()]; // Allocate memory for the maximum
// expected number of fields
fieldCount = 0;
// Split the data string into fields
int lastIndex = 0;
int commaIndex = data.indexOf(',');
while (commaIndex != -1) {
fields[fieldCount] = data.substring(lastIndex, commaIndex);
fieldCount++;
lastIndex = commaIndex + 1;
commaIndex = data.indexOf(',', lastIndex);
}
fields[fieldCount] = data.substring(lastIndex);
fieldCount++;
return fields;
}
void initializeWifi(void) {
Serial.println("Initializing WiFi");
wifiMulti.addAP(ssid, password);
while (wifiMulti.run() != WL_CONNECTED) {
Serial.print(".");
delay(500);
}
Serial.print("IP address: ");
Serial.println(WiFi.localIP());
}
void proximity_handler(void) {
int proximity_value;
proximity_value = vcnl4040.getProximity();
if (proximity_value > 50) {
if (sd == true) {
Serial.println(F_name);
File myFile = SD.open(F_name, FILE_APPEND);
if (myFile) {
myFile.print(N_date);
myFile.print(",");
myFile.print(hour0);
myFile.print(",");
myFile.print(lat0);
myFile.print(",");
myFile.print(lng0);
myFile.print(",");
myFile.println(gps.altitude.meters());
myFile.close();
}
}
Serial.println("Proximity Value:");
Serial.println(proximity_value);
coin_counter += 1;
// Store Coin Counter to SD
writeIntToSD("coin_counter.txt", coin_counter);
delay(1500);
}
}
void wappsto_transmit(void) {
if (digitalRead(WIO_KEY_B) == LOW) {
int line_counter = 0;
// Log to SD card
if (sd == true) {
File myFile = SD.open(F_name, FILE_READ);
if (myFile) {
while (myFile.available()) {
int fieldCount;
String line = myFile.readStringUntil('\n');
if (line.length() > 0) {
Serial.println(line);
String *fields = parseCSV(line, fieldCount);
// Print the fields
for (int i = 0; i < fieldCount; i++) {
Serial.print("Field ");
Serial.print(i);
Serial.print(": ");
Serial.println(fields[i]);
if (i == 2) {
myLatitude = fields[i].toDouble();
} else if (i == 3) {
myLongitude = fields[i].toDouble();
}
}
delete[] fields; // Deallocate the memory used for the fields array
if (line_counter >= wappsto_transmited_lines) {
if (myLatitude > 0) {
Serial.print("Transmited line: ");
Serial.println(line_counter);
updateLocation(myLatitude, myLongitude);
wappsto.dataAvailable();
}
wappsto_transmited_lines++;
}
line_counter++;
}
}
myFile.close();
Serial.print("Updating transmitted lines to: ");
Serial.println(wappsto_transmited_lines);
writeIntToSD("wappsto_transmitted_lines.txt", wappsto_transmited_lines);
} else {
Serial.println("Failed to open file");
}
while (digitalRead(WIO_KEY_B) == LOW) {
}
}
}
}
void setup() {
Serial.begin(57600);
pinMode(WIO_KEY_A, INPUT_PULLUP);
pinMode(WIO_KEY_B, INPUT_PULLUP);
pinMode(WIO_KEY_C, INPUT_PULLUP);
pinMode(WIO_5S_PRESS, INPUT_PULLUP);
pinMode(BUZZER_PIN, OUTPUT);
if (digitalRead(WIO_5S_PRESS) == HIGH) {
mySerial.begin(9600);
}
// Let things stablize (better than !Serial for this case)
delay(2000);
tft.begin();
tft.setRotation(3);
Serial.print("Initializing SD card...");
if (!SD.begin(SDCARD_SS_PIN, SDCARD_SPI)) {
Serial.println("initialization failed!");
sd = false;
tft.drawChar(295, 223, 'S', TFT_WHITE, TFT_RED, 2);
tft.drawChar(307, 223, 'D', TFT_WHITE, TFT_RED, 2);
} else {
Serial.println("initialization done.");
sd = true;
}
// Display splash screen
tft.setFreeFont(&FreeSerifBoldItalic12pt7b);
tft.fillScreen(TFT_WHITE);
tft.setTextColor(TFT_RED);
tft.drawString("Charity Sower", 90, 10);
drawImage<uint16_t>("coin.bmp", 100, 50);
delay(5000);
tft.fillScreen(TFT_BLACK); // Black background
tft.setTextColor(TFT_YELLOW);
// read the stored integer from the SD card
coin_counter = readIntFromSD("coin_counter.txt");
// for satellites position
// Initialize all the uninitialized TinyGPSCustom objects
for (int i = 0; i < 4; ++i) {
satNumber[i].begin(gps, "GPGSV", 4 + 4 * i); // offsets 4, 8, 12, 16
elevation[i].begin(gps, "GPGSV", 5 + 4 * i); // offsets 5, 9, 13, 17
azimuth[i].begin(gps, "GPGSV", 6 + 4 * i); // offsets 6, 10, 14, 18
snr[i].begin(gps, "GPGSV", 7 + 4 * i); // offsets 7, 11, 15, 19
}
if (!vcnl4040.begin()) {
Serial.println("Couldn't find VCNL4040 chip");
while (1)
;
}
Serial.println("Found VCNL4040 chip");
if (digitalRead(WIO_5S_PRESS) == HIGH) {
Serial.println("Skip Wifi Setup");
skip_wifi = true;
} else {
initializeWifi();
initializeNtp();
wappsto.config(network_uuid, ca, client_crt, client_key, 5, NO_LOGS);
if (wappsto.connect()) {
Serial.println("Connected to Wappsto");
} else {
Serial.println("Could not connect");
}
Serial.println("Create network");
myNetwork = wappsto.createNetwork("Location Example");
Serial.println("Create Device");
myDevice = myNetwork->createDevice(&myDeviceDescription);
Serial.println("Create Default val");
myLatitudeValue = myDevice->createNumberValue(&defaultLatitudeParameter);
myLongitudeValue = myDevice->createNumberValue(&defaultLongitudeParameter);
Serial.println("Register callbacks");
myLatitudeValue->onRefresh(&refreshLocationCallback);
myLongitudeValue->onRefresh(&refreshLocationCallback);
Serial.println("read last entry transmitted to wappsto");
wappsto_transmited_lines = readIntFromSD("wappsto_transmitted_lines.txt");
Serial.print("Last transmitted line:");
Serial.println(wappsto_transmited_lines);
}
}
void loop() {
if (skip_wifi == false) {
Serial.println('.');
wappsto.dataAvailable();
delay(500);
}
while (mySerial.available() > 0) {
char c = mySerial.read();
// Serial.print(c);
gps.encode(c);
}
displayInfo();
displayInfoData();
proximity_handler();
// Screen toggle
if (digitalRead(WIO_KEY_C) == LOW) { // Page(menu) change
menu++;
if (menu > 1) menu = 0;
while (digitalRead(WIO_KEY_C) == LOW) {
}
}
if (coin_counter > 10) {
playTone(500, 1000);
coin_counter = 0;
}
// Handle transmitting of stored coordinates to wappstop incase we are in wifi
// on mode.
wappsto_transmit();
}

התוצאה הסופית












מילות סיכום

שמחתי מאד לבצע את הפרוייקט בשיתוף עם חברת Seeed. יהיו אולי כאלו שיתהו על השילוב של רוחניות וטכנולוגיה, אבל זה חלק ממי שאני. אני להוט להתחבר, לשתף ולדון עם אחרים שחולקים נקודות מבט דומות.
ניתן ליצור קשר בתגובות וכן בקישור הזה: http://linktr.ee/asafmatan