สารบัญ:
- ขั้นตอนที่ 1: เขียนโปรแกรมและคอมไพล์ไฟล์ Hex โดยใช้ Atmel Studio
- ขั้นตอนที่ 2: การเปลี่ยนการกำหนดค่าเริ่มต้นของ Micro Controller Fuse Bits
- ขั้นตอนที่ 3: เบิร์นโปรแกรมลงในหน่วยความจำของไมโครคอนโทรลเลอร์ ATMega328P
- ขั้นตอนที่ 4: ตรวจสอบว่าไมโครคอนโทรลเลอร์ทำงานตามคำแนะนำของโปรแกรมของเรา
- ขั้นตอนที่ 5: บทสรุป
วีดีโอ: การกำหนดค่าฟิวส์บิตไมโครคอนโทรลเลอร์ AVR การสร้างและการอัปโหลดในหน่วยความจำแฟลชของไมโครคอนโทรลเลอร์โปรแกรมไฟ LED กะพริบ: 5 ขั้นตอน
2024 ผู้เขียน: John Day | [email protected]. แก้ไขล่าสุด: 2024-01-30 13:06
ในกรณีนี้ เราจะสร้างโปรแกรมอย่างง่ายในโค้ด C และเบิร์นลงในหน่วยความจำของไมโครคอนโทรลเลอร์ เราจะเขียนโปรแกรมของเราเองและรวบรวมไฟล์ hex โดยใช้ Atmel Studio เป็นแพลตฟอร์มการพัฒนาแบบบูรณาการ เราจะกำหนดค่าบิตฟิวส์และอัปโหลดไฟล์ hex ลงในหน่วยความจำของไมโครคอนโทรลเลอร์ AVR ATMega328P โดยใช้โปรแกรมเมอร์และซอฟต์แวร์ AVRDUDE ของเราเอง
AVRDUDE - เป็นโปรแกรมสำหรับดาวน์โหลดและอัปโหลดหน่วยความจำบนชิปของไมโครคอนโทรลเลอร์ AVR ของ Atmel มันสามารถตั้งโปรแกรมแฟลชและ EEPROM และในที่ที่สนับสนุนโดยโปรโตคอลการเขียนโปรแกรมแบบอนุกรม มันสามารถตั้งโปรแกรมฟิวส์และล็อคบิตได้
ขั้นตอนที่ 1: เขียนโปรแกรมและคอมไพล์ไฟล์ Hex โดยใช้ Atmel Studio
หากคุณไม่มี Atmel Studio คุณควรดาวน์โหลดและติดตั้ง:
โปรเจ็กต์นี้จะใช้ C ดังนั้นให้เลือกตัวเลือก GCC C Executable Project จากรายการเทมเพลตเพื่อสร้างโปรเจ็กต์ที่เรียกใช้งานได้โดยเปล่าประโยชน์
ถัดไป มีความจำเป็นต้องระบุอุปกรณ์ที่จะพัฒนาโครงการ โครงการนี้จะได้รับการพัฒนาสำหรับไมโครคอนโทรลเลอร์ AVR ATMega328P
พิมพ์รหัสของโปรแกรมในพื้นที่ Main Source Editor ของ Atmel Studio Main Source Editor – หน้าต่างนี้เป็นตัวแก้ไขหลักสำหรับไฟล์ต้นฉบับในโปรเจ็กต์ปัจจุบัน ตัวแก้ไขมีคุณสมบัติการตรวจตัวสะกดและการเติมข้อความอัตโนมัติ
1. เราต้องบอกคอมไพเลอร์ด้วยความเร็วที่ชิปของเราทำงาน เพื่อให้สามารถคำนวณความล่าช้าได้อย่างเหมาะสม
#ifndef F_CPU
#define F_CPU 16000000UL // บอกความถี่คริสตัลคอนโทรลเลอร์ (16 MHz AVR ATMega328P) #endif
2. เรารวมคำนำ ซึ่งเป็นที่ที่เราใส่ข้อมูลจากไฟล์อื่น ๆ ซึ่งกำหนดตัวแปรและฟังก์ชันส่วนกลาง
#include //header เพื่อเปิดใช้งานการควบคุมการไหลของข้อมูลบนพิน กำหนดพิน พอร์ต ฯลฯ
#include //header เพื่อเปิดใช้งานฟังก์ชั่นการหน่วงเวลาในโปรแกรม
3. หลังจากคำนำมีฟังก์ชัน main()
int หลัก (เป็นโมฆะ) {
ฟังก์ชัน main() มีลักษณะเฉพาะและแยกออกจากฟังก์ชันอื่นๆ ทั้งหมด โปรแกรม C ทุกโปรแกรมต้องมีฟังก์ชัน main() เพียงฟังก์ชันเดียว Main() คือตำแหน่งที่ AVR เริ่มรันโค้ดของคุณเมื่อเปิดเครื่องครั้งแรก จึงเป็นจุดเริ่มต้นของโปรแกรม
4.ตั้งค่าพิน 0 ของ PORTB เป็นเอาต์พุต
DDRB=0b00000001; //ตั้งค่า PORTB1 เป็นเอาต์พุต
เราทำสิ่งนี้โดยการเขียนเลขฐานสองไปยัง Data Direction Register B. Data Direction Register B ช่วยให้เราสร้างบิตของ register B อินพุตหรือเอาต์พุต การเขียน 1 ทำให้เป็นเอาต์พุต ในขณะที่ 0 จะทำให้เป็นอินพุต เนื่องจากเรากำลังติด LED เพื่อทำหน้าที่เป็นเอาต์พุต เราจึงเขียนเลขฐานสอง ทำให้พิน 0 ของ PORT B เป็นเอาต์พุต
5. วนรอบ
ในขณะที่ (1) {
คำสั่งนี้เป็นลูป ซึ่งมักเรียกว่าลูปหลักหรือลูปเหตุการณ์ รหัสนี้เป็นจริงเสมอ ดังนั้นจึงดำเนินการซ้ำแล้วซ้ำอีกในวงอนันต์ มันไม่เคยหยุด ดังนั้นไฟ LED จะกะพริบเป็นช่วงอนันต์ เว้นแต่จะปิดไฟจากไมโครคอนโทรลเลอร์หรือรหัสถูกลบออกจากหน่วยความจำของโปรแกรม
6. เปิดไฟ LED ที่ต่อกับพอร์ต PB0
PORTB= 0b00000001; //เปิดไฟ LED ที่ต่อกับพอร์ต PB0
บรรทัดนี้ให้ 1 กับ PB0 ของ PortB PORTB คือการลงทะเบียนฮาร์ดแวร์บนชิป AVR ที่มี 8 พิน PB7-PB0 โดยเริ่มจากซ้ายไปขวา การใส่ 1 ต่อท้ายจะทำให้ได้ 1 ถึง PB0; สิ่งนี้ทำให้ PB0 สูงซึ่งเปิดใช้งาน ดังนั้น LED ที่ติดอยู่กับพิน PB0 จะเปิดขึ้นและสว่างขึ้น
7. ล่าช้า
_delay_ms(1000); //สร้างการหน่วงเวลา 1 วินาที
คำสั่งนี้สร้างการหน่วงเวลา 1 วินาที เพื่อให้ LED ติดสว่างเป็นเวลา 1 วินาที
8. ปิดพิน B ทั้งหมด รวมถึง PB0
PORTB= 0b00000000; //ปิดพิน B ทั้งหมด รวมถึง PB0
บรรทัดนี้จะปิดพินพอร์ต B ทั้งหมด 8 พิน ดังนั้นแม้แต่ PB0 ก็ดับ ดังนั้นไฟ LED จะดับลง
9. อีกล่าช้า
_delay_ms(1000); //สร้างการหน่วงเวลาอีก 1 วินาที
มันดับลงเป็นเวลา 1 วินาทีก่อนที่จะเริ่มวนซ้ำอีกครั้งและพบกับเส้นซึ่งเปิดขึ้นอีกครั้ง ทำซ้ำขั้นตอนทั้งหมด สิ่งนี้เกิดขึ้นอย่างไม่สิ้นสุดเพื่อให้ไฟ LED ติดและดับตลอดเวลา
10. ส่งคืนคำสั่ง
}
กลับ (0); //บรรทัดนี้ไม่ถึงจริงๆ }
บรรทัดสุดท้ายของโค้ดของเราคือคำสั่ง return(0) แม้ว่าโค้ดนี้จะไม่มีวันถูกเรียกใช้งาน เนื่องจากมีลูปที่ไม่มีที่สิ้นสุดซึ่งไม่มีวันสิ้นสุด สำหรับโปรแกรมของเราที่ทำงานบนคอมพิวเตอร์เดสก์ท็อป ระบบปฏิบัติการจะต้องรู้ว่าโค้ดนั้นทำงานอย่างถูกต้องหรือไม่ ด้วยเหตุผลดังกล่าว GCC ซึ่งเป็นคอมไพเลอร์ของเราจึงต้องการให้ทุก main() ลงท้ายด้วยโค้ดส่งคืน รหัสส่งคืนไม่จำเป็นสำหรับรหัส AVR ซึ่งทำงานอิสระของระบบปฏิบัติการที่รองรับ อย่างไรก็ตาม คอมไพเลอร์จะส่งคำเตือนหากคุณไม่จบ main ด้วย return()
ขั้นตอนสุดท้ายคือการสร้างโครงการ หมายถึงการรวบรวมและสุดท้ายเชื่อมโยงไฟล์อ็อบเจ็กต์ทั้งหมดเพื่อสร้างไฟล์ปฏิบัติการ (.hex) ไฟล์ hex นี้ถูกสร้างขึ้นภายในโฟลเดอร์ Debug ซึ่งอยู่ภายในโฟลเดอร์ Project ไฟล์ hex นี้พร้อมที่จะโหลดลงในชิปไมโครคอนโทรลเลอร์
ขั้นตอนที่ 2: การเปลี่ยนการกำหนดค่าเริ่มต้นของ Micro Controller Fuse Bits
สิ่งสำคัญคือต้องจำไว้ว่าบิตฟิวส์บางตัวสามารถใช้เพื่อล็อคบางแง่มุมของชิปและอาจทำให้เกิดอิฐได้ (ทำให้ใช้งานไม่ได้)
มีฟิวส์บิตทั้งหมด 19 ชิ้นที่ใช้ใน ATmega328P และแยกออกเป็นสามไบต์ของฟิวส์ที่แตกต่างกัน ฟิวส์บิตสามชิ้นมีอยู่ใน "Extended Fuse Byte" แปดชิ้นอยู่ใน "Fuse High Byte" และอีกแปดชิ้นอยู่ใน "Fuse Low Byte" นอกจากนี้ยังมีไบต์ที่สี่ที่ใช้ในการตั้งโปรแกรมบิตล็อค
แต่ละไบต์คือ 8 บิต และแต่ละบิตเป็นการตั้งค่าหรือแฟล็กแยกต่างหาก เมื่อเราพูดถึงการตั้งค่า ไม่ใช่การตั้งค่า โปรแกรม ไม่ใช่ฟิวส์ที่ตั้งโปรแกรมไว้ เรากำลังใช้เลขฐานสองอยู่ 1 หมายถึง ไม่ได้ตั้งค่า ไม่ได้ตั้งโปรแกรมไว้ และศูนย์ หมายถึง ตั้งค่าแล้ว ตั้งโปรแกรมไว้ เมื่อตั้งโปรแกรมฟิวส์ คุณสามารถใช้สัญกรณ์ไบนารีหรือสัญกรณ์เลขฐานสิบหกทั่วไป
ชิป ATmega 328P มีออสซิลเลเตอร์ RC ในตัวซึ่งมีความถี่ 8 MHz ชิปใหม่ถูกจัดส่งพร้อมกับชุดนี้เป็นแหล่งสัญญาณนาฬิกาและฟิวส์ CKDIV8 ทำงานอยู่ ส่งผลให้นาฬิการะบบ 1 MHz เวลาเริ่มต้นถูกตั้งค่าเป็นสูงสุดและเปิดใช้งานช่วงหมดเวลา
ชิป ATMega 328P ใหม่โดยทั่วไปมีการตั้งค่าฟิวส์ต่อไปนี้:
ฟิวส์ต่ำ = 0x62 (0b01100010)
ฟิวส์สูง = 0xD9 (0b11011001)
ฟิวส์ขยาย = 0xFF (0b11111111)
เราจะใช้ชิป ATmega 328 กับคริสตัล 16MHz ภายนอก ดังนั้นเราจึงจำเป็นต้องตั้งโปรแกรมบิตของ "Fuse Low Byte" ตามลำดับ
1. บิต 3-0 ควบคุมตัวเลือกออสซิลเลเตอร์ และการตั้งค่าเริ่มต้นที่ 0010 คือการใช้ออสซิลเลเตอร์ RC ภายในที่ปรับเทียบแล้ว ซึ่งเราไม่ต้องการ เราต้องการการทำงานของคริสตัลออสซิลเลเตอร์พลังงานต่ำจาก 8.0 ถึง 16.0 MHz ดังนั้นบิต 3-1 (CKSEL[3:1]) ควรตั้งค่าเป็น 111
2. Bits 5 และ 4 ควบคุมเวลาเริ่มต้น และการตั้งค่าเริ่มต้นที่ 10 ใช้สำหรับหน่วงเวลาการเริ่มต้นระบบ 6 รอบนาฬิกาจากการปิดเครื่องและประหยัดพลังงาน บวกกับความล่าช้าในการเริ่มต้นเพิ่มเติม 14 รอบนาฬิกา บวก 65 มิลลิวินาทีจากการรีเซ็ต
เพื่อความปลอดภัยสำหรับคริสตัลออสซิลเลเตอร์พลังงานต่ำ เราต้องการดีเลย์สูงสุดที่เป็นไปได้ 16,000 รอบนาฬิกาจากการปิดเครื่องและประหยัดพลังงาน ดังนั้นควรตั้งค่า SUT[1] เป็น 1 บวกกับความล่าช้าในการเริ่มต้นเพิ่มเติม จาก 14 รอบนาฬิกา บวก 65 มิลลิวินาทีจากการรีเซ็ต ดังนั้นควรตั้งค่า SUT[0] เป็น 1 นอกจากนี้ ควรตั้งค่า CKSEL[0] เป็น 1
3. บิต 6 ควบคุมเอาต์พุตนาฬิกาเป็น PORTB0 ซึ่งเราไม่สนใจ ดังนั้น บิต 6 สามารถตั้งค่าเป็น 1 ได้
4. บิต 7 ควบคุมการดำเนินการหารด้วย 8 และการตั้งค่าเริ่มต้นเป็น 0 มีการเปิดใช้งานคุณลักษณะ ซึ่งเราไม่ต้องการ ดังนั้นบิต 7 ต้องเปลี่ยนจาก 0 เป็น 1
ดังนั้น Fuse Low Byte ใหม่ควรเป็น 11111111 ซึ่งในรูปแบบเลขฐานสิบหกคือ 0xFF
ในการโปรแกรมบิตของ "Fuse Low Byte" เราสามารถใช้โปรแกรมเมอร์ของเรา (https://www.instructables.com/id/ISP-Programmer-fo…) และซอฟต์แวร์ AVRDUDE AVRDUDE เป็นยูทิลิตี้บรรทัดคำสั่งที่ใช้ในการดาวน์โหลดและอัปโหลดไปยังไมโครคอนโทรลเลอร์ Atmel
ดาวน์โหลด AVRDUDE:
ขั้นแรก เราต้องเพิ่มคำอธิบายโปรแกรมเมอร์ของเราลงในไฟล์กำหนดค่าของ AVRDUDE ใน Windows ไฟล์การกำหนดค่ามักจะอยู่ในตำแหน่งเดียวกับไฟล์เรียกทำงานของ AVRDUDE
วางข้อความในไฟล์กำหนดค่า avrdude.conf:
#ISPProgv1
โปรแกรมเมอร์ id = " ISPProgv1"; desc = "การกระแทกพอร์ตอนุกรม reset=dtr sck=rts mosi=txd miso=cts"; พิมพ์ = "เซิร์บ"; connection_type = อนุกรม; รีเซ็ต = 4; สค = 7; โมซี = 3; มิโซะ = 8;;
ก่อนเริ่ม AVRDUDE เราต้องเชื่อมต่อไมโครคอนโทรลเลอร์กับโปรแกรมเมอร์ตามแบบแผน
เปิดหน้าต่างพรอมต์ของ DOS
1. หากต้องการดูรายชื่อโปรแกรมเมอร์ที่รองรับ avrdude ให้พิมพ์คำสั่ง avrdude -c c ถ้าทั้งหมดเรียบร้อย รายการควรมีโปรแกรมเมอร์ id "ISPProgv1"
2. หากต้องการดูรายการอุปกรณ์ Atmel ที่รองรับ avrdude ให้พิมพ์คำสั่ง avrdude -c ISPProgv1 รายการควรมีอุปกรณ์ m328p สำหรับ Atmel ATMega 328P
ถัดไป พิมพ์ avrdude -c ISPProgv1 –p m328p คำสั่งบอก avrdude ว่าโปรแกรมเมอร์กำลังใช้อะไรและสิ่งที่แนบมากับไมโครคอนโทรลเลอร์ Atmel แสดงลายเซ็น ATmega328P ในรูปแบบเลขฐานสิบหก: 0x1e950f มันนำเสนอการเขียนโปรแกรมบิตฟิวส์ในปัจจุบันใน ATmega328P ในรูปแบบเลขฐานสิบหก ในกรณีนี้ ไบต์ฟิวส์จะถูกตั้งโปรแกรมไว้ตามค่าเริ่มต้นจากโรงงาน
ถัดไป ให้พิมพ์ avrdude -c ISPProgv1 –p m328p –U lfuse:w:0xFF:m เป็นคำสั่งที่บอกให้ทราบว่าโปรแกรมเมอร์กำลังใช้อะไร และไมโครคอนโทรลเลอร์ Atmel แนบอะไร และเปลี่ยน Fuse Low Byte เป็น 0xFF
ตอนนี้สัญญาณนาฬิกาควรมาจากคริสตัลออสซิลเลเตอร์กำลังต่ำ
ขั้นตอนที่ 3: เบิร์นโปรแกรมลงในหน่วยความจำของไมโครคอนโทรลเลอร์ ATMega328P
ขั้นแรก ให้คัดลอกไฟล์ฐานสิบหกของโปรแกรมที่เราสร้างไว้ตอนต้นของคำสั่งไปยังไดเร็กทอรี AVRDUDE
จากนั้นพิมพ์ในหน้าต่างพรอมต์ DOS คำสั่ง avrdude –c ISPProgv1 –p m328p –u –U flash:w:[ชื่อไฟล์ hex ของคุณ]
คำสั่งเขียนไฟล์ hex ไปยังหน่วยความจำของไมโครคอนโทรลเลอร์ ตอนนี้ไมโครคอนโทรลเลอร์ทำงานตามคำแนะนำของโปรแกรมของเรา มาลองดูกัน!
ขั้นตอนที่ 4: ตรวจสอบว่าไมโครคอนโทรลเลอร์ทำงานตามคำแนะนำของโปรแกรมของเรา
เชื่อมต่อส่วนประกอบตามแผนผังของวงจรไฟ LED กะพริบ AVR
อันดับแรก เราต้องการพลังงาน เช่นเดียวกับวงจร AVR ทั้งหมด กำลังไฟประมาณ 5 โวลต์เพียงพอสำหรับการทำงานของชิป AVR คุณสามารถรับสิ่งนี้ได้จากแบตเตอรี่หรือแหล่งจ่ายไฟ DC เราเชื่อมต่อพลังงาน +5V กับพิน 7 และเชื่อมต่อพิน 8 กับกราวด์บนเขียงหั่นขนม ระหว่างพินทั้งสอง เราวางตัวเก็บประจุเซรามิก 0.1μF เพื่อทำให้กำลังของแหล่งจ่ายไฟราบรื่นขึ้น เพื่อให้ชิป AVR ได้สายไฟที่ราบรื่น
ตัวต้านทาน 10KΩ ใช้เพื่อตั้งค่า Power On Reset (POR) ให้กับอุปกรณ์ เมื่อเปิดเครื่อง แรงดันไฟฟ้าข้ามตัวเก็บประจุจะเป็นศูนย์ ดังนั้นอุปกรณ์จะรีเซ็ต (เนื่องจากการรีเซ็ตทำงานในระดับต่ำ) จากนั้นตัวเก็บประจุจะชาร์จไปที่ VCC และการรีเซ็ตจะถูกปิดใช้งาน
เราเชื่อมต่อขั้วบวกของ LED ของเรากับ AVR pin PB0 นี่คือพิน 14 ของ ATMega328P เนื่องจากเป็น LED เราจึงต้องการจำกัดกระแสที่ไหลไปยัง LED เพื่อไม่ให้เกิดภาวะหมดไฟ นี่คือเหตุผลที่เราวางตัวต้านทาน 330Ω เป็นอนุกรมพร้อมกับ LED แคโทดของ LED เชื่อมต่อกับกราวด์
คริสตัล 16 MHz ใช้เพื่อจัดเตรียมนาฬิกาสำหรับไมโครคอนโทรลเลอร์ Atmega328 และตัวเก็บประจุ 22pF ใช้เพื่อทำให้การทำงานของคริสตัลมีเสถียรภาพ
นี่คือการเชื่อมต่อทั้งหมดที่จำเป็นในการทำให้ไฟ LED สว่างขึ้น แหล่งจ่ายไฟ
ตกลง. ไฟ LED กะพริบโดยมีความล่าช้าหนึ่งวินาที การทำงานของไมโครคอนโทรลเลอร์สอดคล้องกับงานของเรา
ขั้นตอนที่ 5: บทสรุป
เป็นที่ยอมรับว่าเป็นกระบวนการที่ยาวนานสำหรับเพียงแค่กระพริบ LED แต่ความจริงก็คือคุณประสบความสำเร็จในการขจัดอุปสรรคสำคัญ: การสร้างแพลตฟอร์มฮาร์ดแวร์สำหรับการเขียนโปรแกรมไมโครคอนโทรลเลอร์ AVR การใช้ Atmel Studio เป็นแพลตฟอร์มการพัฒนาแบบบูรณาการ โดยใช้ AVRDUDE เป็นซอฟต์แวร์สำหรับ การกำหนดค่าและการเขียนโปรแกรมไมโครคอนโทรลเลอร์ AVR
หากคุณต้องการติดตามข่าวสารล่าสุดเกี่ยวกับโปรเจ็กต์ไมโครคอนโทรลเลอร์พื้นฐานของฉัน สมัครสมาชิก YouTube ของฉัน! การรับชมและแชร์วิดีโอเป็นวิธีสนับสนุนสิ่งที่ฉันทำ
สมัครสมาชิกช่อง YouTube FOG
แนะนำ:
StickC M5Stack LED กะพริบ: 7 ขั้นตอน
StickC M5Stack LED Blink: ในโครงการนี้ เราจะเรียนรู้วิธีเชื่อมต่อและสร้าง LED Blink โดยใช้โมดูล M5StickC ESP32 ดูวิดีโอ
ไฟ LED เล็กๆ กะพริบ: 6 ขั้นตอน
รูป LED กะพริบเล็ก ๆ : คุณสามารถกะพริบ LED ได้อย่างง่ายดายด้วยตัวจับเวลา Arduino หรือ 555 แต่คุณสามารถสร้างวงจรกะพริบได้โดยไม่ต้องใช้ไอซีดังกล่าว นี่เป็นหุ่นที่กะพริบง่าย ๆ ที่ทำจากชิ้นส่วนที่ไม่ต่อเนื่อง
RIG CELL LITE INTRO: ไฟ LED กะพริบ: 4 ขั้นตอน
RIG CELL LITE INTRO: ไฟ LED กะพริบ: บทนำ ไฟ LED เป็นไฟขนาดเล็กและทรงพลังซึ่งใช้งานในหลากหลายรูปแบบ ในการเริ่มต้น เราจะทำการกะพริบ LED ซึ่งเป็น Hello World ของไมโครคอนโทรลเลอร์ ใช่แล้ว ง่ายเหมือนการเปิดและปิดไฟ มัน
ไฟ LED กะพริบ {ควบคุมด้วยปุ่ม}: 5 ขั้นตอน
ไฟ LED กะพริบ {ปุ่มควบคุม}: ฉันเป็นนักเรียนที่ Kang Chiao นี่คือโครงการของฉัน ฉันใช้ Arduino และสร้างไฟ LED กะพริบพร้อมปุ่มที่ทำให้กะพริบได้ คุณสามารถวางบนผ้าของคุณ และเมื่อมีคนอยู่ใกล้คุณเกินไป คุณสามารถกดปุ่มและหลอดไฟพร้อม
ไฟ LED สีเขียว (ควบคุมด้วยไฟ LED กะพริบ): 9 ขั้นตอน
หลอดไฟ LED สีเขียว (ควบคุมด้วยไฟ LED กะพริบ): เมื่อไม่กี่ปีก่อน ฉันอ่านบทความเกี่ยวกับระบบแสงสว่างในประเทศกำลังพัฒนา มันบอกว่าผู้คน 1.6 พันล้านคนไม่มีไฟฟ้าใช้ และแหล่งกำเนิดแสงที่เชื่อถือได้เป็นปัญหาใหญ่สำหรับพวกเขา บริษัทแห่งหนึ่งในแคนาดาผลิตและจำหน่าย lightin…