This shows you the differences between two versions of the page.
— | en:book [2023/09/07 10:01] (current) – created - external edit 127.0.0.1 | ||
---|---|---|---|
Line 1: | Line 1: | ||
+ | ======= Authors ======= | ||
+ | |||
+ | IOT-OPEN.EU Reloaded Consortium partners proudly present the 2nd edition of the Introduction to the IoT book. The complete list of contributors is juxtaposed below. | ||
+ | |||
+ | === ITT Group === | ||
+ | * Raivo Sell, Ph. D., ING-PAED IGIP | ||
+ | * Rim Puks, Eng. | ||
+ | * Mallor Kingsepp, Eng. | ||
+ | |||
+ | === Riga Technical University === | ||
+ | * Agris Nikitenko, Ph. D., Eng. | ||
+ | * Karlis Berkolds, M. sc., Eng. | ||
+ | * Anete Vagale, M. sc., Eng. | ||
+ | * Rudolfs Rumba, M. sc., Eng. | ||
+ | |||
+ | === Silesian University of Technology === | ||
+ | * Piotr Czekalski, Ph. D., Eng. | ||
+ | * Krzysztof Tokarz, Ph. D., Eng. | ||
+ | * Oleg Antemijczuk, | ||
+ | * Jarosław Paduch, M. sc., Eng. | ||
+ | * Godlove Suila Kuaban, M. sc., Eng. | ||
+ | |||
+ | === Tallinn University of Technology === | ||
+ | * Raivo Sell, Ph. D., ING-PAED IGIP | ||
+ | * Karl Läll, B. sc., Eng. | ||
+ | |||
+ | === SIA RobotNest === | ||
+ | * Karlis Berkolds, M. sc., Eng. | ||
+ | |||
+ | === IT Silesia === | ||
+ | * Łukasz Lipka, M. sc., Eng. | ||
+ | |||
+ | === University of Messina === | ||
+ | * Salvatore Distefano | ||
+ | * Rustem Dautov | ||
+ | * Riccardo Di Pietro | ||
+ | * Antonino Longo Minnolo | ||
+ | |||
+ | === ITMO University === | ||
+ | * Aleksandr Kapitonov, Ph. D., Assoc. Prof. | ||
+ | * Dmitrii Dobriborsci, | ||
+ | * Igor Pantiukhin, M. sc., Eng. | ||
+ | * Valerii Chernov, Eng. | ||
+ | |||
+ | ==== Graphic Design and Images ==== | ||
+ | * Blanka Czekalska, M. sc., Eng., Arch. | ||
+ | * Piotr Czekalski, Ph. D., Eng. | ||
+ | |||
+ | ==== Reviewers (1st edition) ==== | ||
+ | * Fabio Bonsignorio, | ||
+ | * Artur Pollak, M. sc., Eng. -- CEO at APAGroup | ||
+ | * Ivars Parkovs, M. sc., Eng. -- R&D Senior Engineer at "SAF Tehnika" | ||
+ | * Janis Lacaunieks, M. sc., Eng. -- R&D Engineer at "SAF Tehnika" | ||
+ | ====== Versions ====== | ||
+ | |||
+ | This page keeps track of the content reviews and versions done as a continuous maintenance process | ||
+ | |||
+ | < | ||
+ | < | ||
+ | ^ ^ Version | ||
+ | | 1 | v 0.1 | 01.05.2023 | ||
+ | | 2 | v 0.2 | 02.05.2023 | ||
+ | | 3 | v 0.25 | 08.05.2023 | ||
+ | | 4 | v 0.26 | 18.06.2023 | ||
+ | | 5 | v 0.27 | 28.06.2023 | ||
+ | | 6 | v 0.28 | 28.06.2023 | ||
+ | | 7 | v 0.29 | 28.06.2023 | ||
+ | | 8 | v.0.3 | 19.08.2023 | ||
+ | | 9 | v.0.31 | ||
+ | | 10 | v.0.32 | ||
+ | </ | ||
+ | ======= Preface ======= | ||
+ | This book and its offshoots were prepared to provide comprehensive information about the Internet of Things on the engineering level.\\ | ||
+ | Its goal is to introduce IoT to bachelor students, master students, technology enthusiasts and engineers willing to extend their current knowledge with the latest hardware and software achievements in the scope of the Internet of Things.\\ | ||
+ | This book is also designated for teachers and educators willing to prepare a course on IoT. | ||
+ | |||
+ | We (Authors) assume that persons willing to study this content possess some general knowledge about IT technology, i.e. understand what an embedded system is, know the general idea of programming (in C/C++) and are aware of wired and wireless networking as it exists nowadays. | ||
+ | |||
+ | This book constitutes a comprehensive manual for IoT technology; however, it is not a complete encyclopedia nor exhausts the market. The reason for it is pretty simple – IoT is so rapidly changing technology that new devices, ideas and implementations appear daily. Once you read this book, you can quickly move over the IoT environment and market, easily chasing ideas and implementing your IoT infrastructure. | ||
+ | |||
+ | We also believe this book will help adults that took their technical education some time ago to update their knowledge. | ||
+ | |||
+ | We hope this book will let you find brilliant ideas in your professional life, see a new hobby, or even start an innovative business. | ||
+ | |||
+ | ** Playing with real or virtual hardware and software is always fun, so keep going! ** | ||
+ | ======= Project Information ======= | ||
+ | ThisBook was implemented under the Erasmus+ KA2 projects: | ||
+ | * Strategic Partnerships in the Field of Education, Training, and Youth – Higher Education, 2016, IOT-OPEN.EU – Innovative Open Education on IoT: Improving Higher Education for European Digital Global Competitiveness, | ||
+ | * Cooperation Partnerships in higher education, 2022, IOT-OPEN.EU Reloaded: Education-based strengthening of the European universities, | ||
+ | |||
+ | **Erasmus+ Disclaimer**\\ | ||
+ | This project has been funded with support from the European Commission. \\ | ||
+ | This publication reflects the views only of the author, and the Commission cannot be held responsible for any use which may be made of the information contained therein. | ||
+ | |||
+ | **Copyright Notice**\\ | ||
+ | This content was created by the IOT-OPEN.EU Consortium: 2016–2019 and IOT-OPEN.EU Reloaded Consortium 2022-2025.\\ | ||
+ | The content is Copyrighted and distributed under CC BY-NC [[https:// | ||
+ | <figure label> | ||
+ | {{en: | ||
+ | </ | ||
+ | In case of commercial use, please contact IOT-OPEN.EU Reloaded Consortium representative. | ||
+ | <box # | ||
+ | <box # | ||
+ | ====== Introduction ====== | ||
+ | <box # | ||
+ | <box # | ||
+ | |||
+ | Here comes the Internet of Things. | ||
+ | The name that recently makes red-hot people in business, researchers, | ||
+ | The name that non-technology related people consider a kind of magic and even a danger to their privacy. | ||
+ | The EU set the name as one of the emerging technologies and estimated the worldwide market will hit well over 500 billion US dollars in 2022, while the number of IoT devices in 2030 is expected to be over 3.2 billion. | ||
+ | |||
+ | What is IoT (Internet of Things), then? | ||
+ | Surprisingly, | ||
+ | |||
+ | |||
+ | |||
+ | ==== Color coding ==== | ||
+ | |||
+ | To simplify the selection of different topics, a simple colour coding was introduced, indicating the skills required to cover particular topics. Colour codes are organized in the form of colour bars enclosing chapter titles. | ||
+ | |||
+ | Explanation: | ||
+ | |||
+ | === === | ||
+ | |||
+ | <box # | ||
+ | <box # | ||
+ | === This chapter is for beginners (including amateurs) or higher === | ||
+ | <box # | ||
+ | <box # | ||
+ | |||
+ | <box # | ||
+ | |||
+ | <box # | ||
+ | <box # | ||
+ | === This chapter is for bachelor students of higher === | ||
+ | <box # | ||
+ | <box # | ||
+ | |||
+ | <box # | ||
+ | |||
+ | <box # | ||
+ | <box # | ||
+ | === This chapter is for master students of higher === | ||
+ | <box # | ||
+ | <box # | ||
+ | |||
+ | |||
+ | ===== ===== | ||
+ | <box # | ||
+ | <box # | ||
+ | ===== Definition of IoT ===== | ||
+ | <box # | ||
+ | <box # | ||
+ | Let us roll back to the 1970s first. | ||
+ | In 1973 the first RFID device was patented. This device was the key enabling technology even if it does not look nor remind modern IoT devices. The low power (actually here passive) solution with a remote antenna large enough to collect energy from the electromagnetic field and power the device brought an idea of uniquely identifiable items. That somehow mimics well-known EAN barcodes and the evolution used nowadays, like QR codes, but every single thing has a different identity here. In contrast, EAN barcodes present a class of products, not an individual one. The possibility to identify a unique identity remotely became fundamental to the IoT as it's known today. RFID is not the only technology standing behind IoT. In the 1990s, the rapid expansion of wireless networks, including broadband solutions like cellular-based data transfers with their consequent generations, | ||
+ | |||
+ | ==== What is IoT? ==== | ||
+ | The phrase " | ||
+ | International Telecommunication Union (ITU) in the ITU Internet report in 2005 (("ITU Internet Reports 2005: The Internet of Things." | ||
+ | The understanding and definitions of IoT changed over the years, but now all agree that this cannot be seen as a technology issue only. | ||
+ | According to IEEE " | ||
+ | ^IEEE Definition of IoT^ | ||
+ | |A network of items – each embedded with sensors – connected to the Internet.| | ||
+ | It relates to the physical aspects of IoT only. The Internet of Things also addresses other aspects that cover many areas ((" | ||
+ | *enabling technologies, | ||
+ | *software, | ||
+ | *applications and services, | ||
+ | *business models, | ||
+ | *social impact, | ||
+ | *security and privacy aspects. | ||
+ | IEEE, as one of the most prominent standardisation organisations, | ||
+ | It is essential to understand that IoT systems are not only small, local-range systems. ITU-T has defined IoT as: | ||
+ | ^ITU-T Definition of IoT^ | ||
+ | |A global infrastructure for the information society, enabling advanced services by interconnecting (physical and virtual) things based on existing and evolving interoperable information and communication technologies.| | ||
+ | In the book ((Ovidiu Vermesan, Peter Friess (eds.): Digitising the Industry, Internet of Things Connecting the Physical, Digital and Virtual Worlds, River Publishers Series in Communications, | ||
+ | IoT impacts many areas of human activity: manufacturing, | ||
+ | In this course, we will consider the technical aspects mainly. | ||
+ | ==== " | ||
+ | In the IoT world, the " | ||
+ | " | ||
+ | ^CERP-IoT Definition of " | ||
+ | |A real/ | ||
+ | It is quite easy to find other terms used in the literature like "smart object", | ||
+ | ===Passive Thing=== | ||
+ | One can imagine that almost everything in our surroundings is tagged with an RFID element. They do not need a power supply; they respond with a short message, usually containing the identification number. Modern RFID can achieve 6 to 7 meters of the range. Using the active RFID reader, we can quickly locate lost keys and know if we still have the butter in the fridge and in which wardrobe there is our favourite t-shirt. | ||
+ | ===Active Thing=== | ||
+ | If the " | ||
+ | Active things can also receive control signals from the central controller to control the environment: | ||
+ | ===Autonomous Thing=== | ||
+ | This thing does not even require the controller to realise the proper decision. An autonomous vacuum cleaner can clean our house when it detects that we aren't home and the floor needs cleaning. The fridge can order our favourite beverage once the last bottle is almost empty. | ||
+ | ====Sensor Network==== | ||
+ | Sensor Networks are a subset of the IoT devices used as a collaborative solution to grab data and send it for further processing. Opposite to the general IoT devices, Sensor Network devices do not have any actuators that can apply an action to the external world. The data flow is unidirectional, | ||
+ | ====IoT vs Embedded Systems==== | ||
+ | IoT systems and embedded systems share almost the same domain. They frequently use the same microcontrollers, | ||
+ | ===== ===== | ||
+ | <box # | ||
+ | <box # | ||
+ | =====Enabling Technologies===== | ||
+ | <box # | ||
+ | <box # | ||
+ | In this chapter, there is an approach to describe modern technologies that appeared in the last few years, enabling the idea of IoT to be widely implementable. In the ((Ovidiu Vermesan, Peter Friess (eds.): Digitising the Industry, Internet of Things Connecting the Physical, Digital and Virtual Worlds, River Publishers Series in Communications, | ||
+ | Similar analysis has been done in ((Ala Al-Fuqaha, Mohsen Guizani, Mehdi Mohammadi, Mohammed Aledhari, Moussa Ayyash: Internet of Things: A Survey on Enabling Technologies, | ||
+ | ====Edge class devices==== | ||
+ | In recent years one can observe rapid growth in the field of microprocessors. It includes not only the powerful desktop processors but also microcontrollers – elements that are used in small-scale embedded systems. We can also notice the popularity of microprocessor systems that can be easily integrated with other factors, like sensors, and actuators, connected to the network. Essential is also the availability of programming tools and environments supported by different companies and communities. An excellent example of such a system is Arduino. Those devices are low-power, constrained devices, usually battery-powered and, in most cases, communicating wirelessly. | ||
+ | ====Fog class devices==== | ||
+ | The same growth can be observed in the advanced constructions comparable to low-end computers. They have more powerful processors, memory and networking connectivity built-in than small-scale computer systems. They can work under the control of multitasking operating systems like Linux and Windows and embedded or real-time operating systems like FreeRTOS. Having many libraries, they can successfully work as hubs for local storage, local controllers and gateways to the Internet. Raspberry Pi and the nVidia Jetson series are examples of such systems. This category of devices frequently contains hardware accelerated (such as GPU) AI-capable solutions, i.e. nVidia Jetson Nano or Xavier series. Those devices can be battery or mains powered. Often, they are green energy powered: i.e. with a larger backup battery and energy harvesting solution (such as solar panel). | ||
+ | ====Access to the Internet==== | ||
+ | Nowadays, the Internet is (almost) everywhere. There are lots of wireless networks available in private and public places. The price of cellular access (3G/4G/5G) is low, offering a suitable data transfer performance. Connecting the " | ||
+ | ====IP Addressing Evolution==== | ||
+ | The primary paradigm of IoT is that every unit can be individually addressed. With the addressing scheme used in IPv4, it wouldn' | ||
+ | ====Data Storage and Processing==== | ||
+ | IoT devices generate the data to be stored and processed somewhere. If there is a couple of sensors, the amount of data is not very big, but if there are thousands of sensors generating data hundreds of times every second. The cloud can handle it – the massive place for the data with tools and applications ready to help with data processing. Some big, global clouds are available for rent, offering not only storage but also Business Intelligence tools, Artificial Intelligence analytic algorithms. There are also smaller private clouds created to cover the needs of one company only. Many universities have their own High-Performance Computing Centre. | ||
+ | ====Mobile Devices==== | ||
+ | Many people want to be connected to the global network everywhere, anytime, having their " | ||
+ | |||
+ | The technologies we mentioned here are the most recognisable. Still, there are many others, more minor, described only in the technical language in some standard description document, hidden under the colourful displays between large data centres, making our IoT world operable. In this book, we will describe some of them. | ||
+ | |||
+ | ====A special note on Fog class and Edge class devices==== | ||
+ | Technology development instantly shifts devices between categories. A border between Fog and Edge class devices is conventional; | ||
+ | <box # | ||
+ | <box # | ||
+ | ===== Mobility – New Paradigm for IoT Systems ===== | ||
+ | <box # | ||
+ | <box # | ||
+ | |||
+ | |||
+ | IoT has already been defined as a network of physical things or devices that might include sensors or simple data processing units, complex actuators, and significant hybrid computing power. Today IoT systems have transitioned from being perceived as sensor networks to smart-networked systems capable of solving complex tasks in mass production, public safety, logistics, medicine and other domains, requiring a broader understanding and acceptance of current technological advancements, | ||
+ | |||
+ | Since the very beginning of sensor networks, one of the main challenges has been data transport and data processing, where significant efforts have been put by the ICT community towards service-based system architectures. However, The current trend already provides considerable computing power even in small mobile devices. Therefore, the concepts of future IoT already shifted towards smarter and more accessible IoT devices, and data processing has become possible closer to the Fog and Edge. | ||
+ | |||
+ | ==== Cloud Computing ==== | ||
+ | |||
+ | Cloud-based computing is a relatively well-known and adequately employed paradigm where IoT devices can interact with remotely shared resources such as data storage, | ||
+ | data processing, data mining and other services are unavailable to them locally because of the constrained hardware resources (CPU, ROM, RAM) or energy consumption limits. | ||
+ | Although the cloud computing paradigm can handle vast amounts of data from IoT clusters, the transfer of extensive data to and from cloud computers presents a challenge due to limited bandwidth((Arslan Munir, IFCIoT: Integrated Fog Cloud IoT Architectural Paradigm for the Future Internet of Things, IEEE Consumer Electronics Magazine, Vol. 6, Issue 3, July 2017 )). | ||
+ | Consequently, | ||
+ | |||
+ | ==== Fog Computing ==== | ||
+ | |||
+ | Fog computing addressed the bottlenecks of cloud computing regarding data transport while providing the needed services to IoT systems. | ||
+ | It is a new trend in computing that aims to process the data near the data source. Fog computing pushes applications, | ||
+ | Fog computing enables data analytics and knowledge generation at the data source. Furthermore, | ||
+ | The recent development of energy-efficient hardware with AI acceleration enters the fog class of the devices, putting Fog Computing in the middle of the interest of IoT application development and extending new horizons to them. Fog Computing is more energy efficient than raw data transfer to the cloud and back, and in the current scale of the IoT devices, the application is meant for the future of the planet Earth. Fog Computing usually also brings a positive impact on IoT security, i.e. sending to the cloud preprocessed and depersonalised data and providing distributed computing capabilities that are more attack resistant. | ||
+ | |||
+ | ==== Edge Computing ==== | ||
+ | Recent development in hardware, power efficiency and a better understanding of the IoT data nature, including such aspects as, i.e. privacy and security, led to solutions where data is being processed and preprocessed right to their source in the Edge class devices. Edge data processing on end-node IoT devices is crucial in systems where privacy is essential and sensitive data is not to be sent over the network (i.e. biometric data in a raw form). Moreover, distributed data processing can be considered more energy efficient in some scenarios where, i.e. extensive, power-consuming processing can be performed during green energy availability. | ||
+ | |||
+ | ==== Cognitive IoT Systems ==== | ||
+ | |||
+ | According to ((S.Matthews at http:// | ||
+ | * **understanding** – in the case of IoT, it means systems' | ||
+ | * **reasoning** – involves decision-making according to the understood model and acquired data; | ||
+ | * **learning** – creating new knowledge from the existing, sensed data and elaborated models. | ||
+ | Usually, cognitive IoT systems or C-IoT are expected to add more resilience to the solution. Resilience is a complex term and is differently explained under different contexts; however, there are standard features for all resilient systems. As a part of their resilience, C-IoT should be capable of self-failure detection and self-healing that minimises or gradually degrades the system' | ||
+ | Recent development in the Fog and Edge class devices and the efficient software leverage cognitive IoT Systems to a new level. | ||
+ | |||
+ | All three approaches, from cloud to cognitive systems, focus on adding value to IoT devices, system users and related systems on-demand. | ||
+ | Since market and technology acceptance of mobile devices is still growing, and the amount of produced data from those devices is growing exponentially, | ||
+ | driving forces of the technological advancements of the near future. | ||
+ | ===== ===== | ||
+ | <box # | ||
+ | <box # | ||
+ | ===== Data Management Aspects in IoT ===== | ||
+ | <box # | ||
+ | <box # | ||
+ | |||
+ | Data management is a critical task in IoT. | ||
+ | Due to the high number of devices (things) already available, that is tens of billions, and considering the data traffic generated by each of them through, i.e. sensor networks, infotainment (soft news) or surveillance systems, mobile social network clients, and so on, we are now even beyond the ZettaByte (ZB 2^70, 10^21 bytes) era. | ||
+ | This opened up several new challenges in (IoT) data management, giving rise to data sciences and big data technologies. | ||
+ | Such challenges have not to be considered as main issues to solve but also as significant opportunities fuelling the digital economy with new directions such as Cloudonomics (([[http:// | ||
+ | Therefore, properly managing data in IoT contexts is not only critical but also of strategic importance for business players as well as for users, evolving into **prosumers** (producers-consumers). | ||
+ | |||
+ | From a technological perspective, | ||
+ | |||
+ | * **data source**: data generation and production is a relevant part of IoT, involving sensors probing the physical system. In a cyber-physical-social system view, such sensors could be virtual (e.g. software) or even human (e.g. citizens, crowdsensing). The main issues in data production are related to the type and format of data, heterogeneity in measurements and similar issues. Semantics is the key to solving these issues, also through specific standards such as Sensor Web Enablement and Semantic Sensor Network; | ||
+ | * **data collection/ | ||
+ | * **filtering**: | ||
+ | * **aggregation/ | ||
+ | * **processing**: | ||
+ | * **storage/ | ||
+ | * **delivering/ | ||
+ | * **security and privacy**: data privacy and security are among the most critical issues in IoT data management. Good results and reliable techniques for secure data transmission, | ||
+ | ===== ===== | ||
+ | <box # | ||
+ | <box # | ||
+ | ===== IoT Application Domains ===== | ||
+ | <box # | ||
+ | <box # | ||
+ | |||
+ | Application domains of the Internet of Things solutions are vast. Most prominent applications include (among others) ((https:// | ||
+ | * building and home automation, | ||
+ | * smart water, | ||
+ | * internet of food, | ||
+ | * smart metering, | ||
+ | * smart city (including logistics, retail, transportation), | ||
+ | * industrial IoT, | ||
+ | * precision agriculture and smart farming, | ||
+ | * security and emergencies, | ||
+ | * healthcare and wellness (including wearables), | ||
+ | * smart environment, | ||
+ | * energy management, | ||
+ | * robotics, | ||
+ | * smart grids. | ||
+ | |||
+ | **Smart Homes** are one of the first examples that come to mind when discussing Internet of Things domain applications. Smart home benefits include reduced energy wastage, the quality and reliability of devices, system security, reduced cost of basic needs, etc. Some home automation examples are environmental control systems that monitor and control heating, ventilation, | ||
+ | |||
+ | In **Smart City**, multiple IoT-based services are applied to different areas of urban settings. The aim of the smart city is the best use of public resources, improvement of the quality of resources provided to people and reduction of operating costs of public administration ((https:// | ||
+ | |||
+ | **Smart Grid** is a digital power distribution system. This system gathers information using smart meters, sensors and other devices. After these data are processed, power distribution can be adapted accordingly. Smart grids deliver sustainable, | ||
+ | |||
+ | In **Precision Agriculture** and **Smart Farming** IoT solutions can be used to monitor the moisture of the soil and conditions of the plants, control microclimate conditions and monitor the weather conditions to improve farming ((https:// | ||
+ | |||
+ | **Internet of Food** integrates many of the aforementioned techniques and encompasses different stages of the food delivery chain, including smart farming, food processing, transportation, | ||
+ | |||
+ | Similar to precision agriculture, | ||
+ | |||
+ | **Industrial IoT** and **smart factories** are part of the Industry 4.0 revolution. In this model, modern factories can automate complex manufacturing tasks, thanks to the Machine-To-Machine communication model, which provides more flexibility in the manufacturing process to enable personalised, | ||
+ | |||
+ | In the **healthcare and wellness**, IoT applications can monitor and diagnose patients and manage people and medical resources. It allows remote and continuous monitor the vital signs of patients to improve medical care and wellness of patients ((https:// | ||
+ | |||
+ | **Wearables** used in IoT applications should be highly energy efficient, ultra-low power and small-sized. Wearables are installed with sensors and software for data and information collected about the user. | ||
+ | Devices used in daily life like Fitbit ((https:// | ||
+ | ====== Introduction to the IoT Microcontrollers ====== | ||
+ | <todo @ktokarz # | ||
+ | |||
+ | IoT device is, in almost all cases, based on microcontroller. A microcontroller, | ||
+ | Microcontrollers are even more complex in the IoT world due to wireless networking capability. A complex microcontroller equipped with an internal radio communication module is also known as a System on Chip (SoC). < | ||
+ | The typical microcontroller includes general-purpose units like: | ||
+ | * CPU core, | ||
+ | * Program memory, | ||
+ | * Data memory, | ||
+ | * Timers, Counters, | ||
+ | * Interrupt controller, | ||
+ | * I/O ports, | ||
+ | * Serial synchronous and asynchronous communication ports, | ||
+ | * Analog to Digital converter, | ||
+ | * PWM (Pulse width Modulation unit for Digital to Analog conversion), | ||
+ | * DMA controller, | ||
+ | * Supervisory units (Watchdog, Reset, Brownout). | ||
+ | Embedded Processor or System on Chip can contain also: | ||
+ | * Network interface, | ||
+ | * USB controller, | ||
+ | * Memory interface module, | ||
+ | * Floating point unit (FPU), | ||
+ | * Cryptographic module, | ||
+ | * Other application-specific extensions. | ||
+ | The **CPU core** is the unit that executes the main program. It controls program flow, executes general-purpose instructions, | ||
+ | The program instructions are fetched from **program memory**, usually implemented as internal or external flash memory. Data is stored in internal **data memory** implemented as static RAM. If more memory is needed, some microcontrollers have a memory management unit that allows them to connect external DRAM memory. Flash memory is often used as a place for file storage. | ||
+ | **Timers and counters** are units that help to generate pulses of specified length and square signals of specified frequency. They can also measure delays and synchronise the work of other modules like serial ports, converters, and displays. Timers can generate pulse width modulated signals to control the speed of motors and light brightness. | ||
+ | Microcontrollers have **digital input and output ports** to connect other elements of the systems. Connecting external sensors to collect information from the surroundings and output devices to manipulate environmental parameters is possible. **Analogue inputs** can read the voltage value generated by simple sensors. | ||
+ | **Serial communication ports** are used to connect more complex sensors and displays to communicate with the user or another computer system. | ||
+ | An **interrupt controller** is a unit that automatically executes subroutines responsible for handling tasks specific to the hardware that signalled the situation that needs the processor' | ||
+ | **Supervisory units** help to recover from some abnormal situations. Watchdog resets the processor in case the software hangs up. Brownout detector constantly monitors the power supply voltage. It stops the processor if the voltage is too low for proper operation to avoid execution errors, flash write errors, and other malfunctions. Supervisory interfaces like JTAG allow writing the programs into flash memory and debugging the code. | ||
+ | **Direct Memory Access** (DMA) module performs memory operations without processor intervention. It is usually used for copying data blocks between memory and other peripheral units. For example, data from the network unit is stored automatically in the buffer, and the CPU is informed while the data transfer is complete. | ||
+ | |||
+ | Details of the internal construction and operation of many internal modules of popular microcontrollers are described in further chapters of this book. | ||
+ | |||
+ | |||
+ | |||
+ | |||
+ | |||
+ | |||
+ | ======= Introduction to Embedded Programming ======= | ||
+ | IoT systems share programming paradigms with embedded systems. Each microcontroller manufacturer has its own set of tools (usually called SDK or Development Framework) that frequently contain an IDE dedicated to the platform. There are some cross-platform solutions and frameworks, however.\\ | ||
+ | Programming languages include: | ||
+ | * C/C++ - undoubtedly the most popular, versatile, yet demanding programming language. With modern supporting tools such as syntax highlights, code samples, code generators (AI-based) and instant syntax checking, C/C++ programming became relatively easy but still requires solid software development foundations. On the other hand, it is probably the only programming language that is natively supported with hardware debugging features. C/C++ bare metal programming allows the developer to control all MCU features on the lowest level and implement energy-efficient, | ||
+ | * Java and Javascript - with low entry-level for developers, usually represented by the variation of NodeJS, limited and applicable to beginners. Within the constraints of the interpreter, | ||
+ | * Python (Micropython) - similarly to Java, offers an easy start but low flexibility and control over the hardware. Acceptable for prototyping. | ||
+ | * Other. | ||
+ | |||
+ | ===== IoT and Embedded Systems Programming Models ===== | ||
+ | IoT device programming can be done on a variety of levels. Below we present the most popular models and briefly discuss their pros and cons.\\ | ||
+ | |||
+ | |||
+ | ==== Bare Metal Programming ==== | ||
+ | The bare metal programming model is where the software developer builds firmware (usually from scratch or based on a stub generated by the SDK) and flashes it to the MCU. The MCU usually does not contain software other than technical ones necessary for starting and updating the device, i.e. a bootloader. The developer must implement all algorithms, communication, | ||
+ | |||
+ | < | ||
+ | |||
+ | Bare metal programming requires a good understanding of the hardware configuration of the IoT device as well as the configuration of the software development toolchain. The MCU manufacturer usually provides SDK and related tools, but there do exist middleware solutions (such as PlatformIO ((https:// | ||
+ | |||
+ | In most cases, source code is written in C or C++ language or their combination (e.g. in the case of the STM). The development process for bare metal programming is present in the following figure {{ref> | ||
+ | |||
+ | <figure prog_img_baremetal> | ||
+ | {{ : | ||
+ | < | ||
+ | </ | ||
+ | |||
+ | The bare metal programming model is considered the only one to enable developers to have absolute control over the hardware on a very low level. On the one hand, it brings opportunities to implement non-standard solutions and optimal code in terms of compactness and efficiency; on the other, it increases time-to-market delivery. Recent advances in development supporting tools (i.e. AI-based code generation), | ||
+ | |||
+ | <table prog_tbl_baremetal> | ||
+ | < | ||
+ | ^ Pros ^ Cons ^ | ||
+ | | Absolute control over hardware | ||
+ | | Secure, low vulnerability | ||
+ | | No bottlenecks | ||
+ | | Efficient and compact code | Requires complex development environment | ||
+ | | Fastest, no overhead of the middleware | ||
+ | | Good community support | ||
+ | | Highly flexible, enables the developer to prepare non-standard solutions | ||
+ | | Provides hardware debugging capabilities | ||
+ | | Energy efficient, it gives control over low-level, energy-saving mechanisms (waitstates, | ||
+ | </ | ||
+ | |||
+ | <note tip> | ||
+ | In the IoT world, it is common to distribute firmware remotely (OTA - Over The Air). For this reason, it is pretty frequent that the flash memory of the IoT device is split in half into two partitions, each containing a different version of the firmware (old and new). OTA mechanism flashes an inactive partition, and then the bootloader swaps them during the reboot of the device once flashing is done. If new firmware fails to boot, the bootloader swaps the partition back to run the old version, reboots the device, and notifies about the update error.</ | ||
+ | |||
+ | ==== Script Programming with Middleware ==== | ||
+ | Opposite to bare metal programming, | ||
+ | |||
+ | < | ||
+ | |||
+ | The development process for scripting programming is present in the following figure {{ref> | ||
+ | |||
+ | <figure prog_img_scripting> | ||
+ | {{ : | ||
+ | < | ||
+ | </ | ||
+ | |||
+ | This programming model is suitable wherever standard solutions are implemented and where code execution efficiency is not critical, and there is no demand for real-time operations; eventually, the IoT device is unconstrained, | ||
+ | |||
+ | <table prog_tbl_scripting> | ||
+ | < | ||
+ | ^ Pros ^ Cons ^ | ||
+ | | Better suitable for beginners | ||
+ | | Uses higher abstraction level | Not suitable for real-time operations | ||
+ | | Uses high-level programming languages | ||
+ | | Usually does not involve complex SDK/ | ||
+ | | Flexible enough to implement complex algorithms | ||
+ | | Rapid development | ||
+ | | | Hardware debugging is tricky or not possible at all | | ||
+ | </ | ||
+ | |||
+ | ==== Configuring Firmware ==== | ||
+ | Several middleware (IoT frameworks) are available for various IoT devices. This development model focuses on reconfiguring the sealed firmware delivered "as is" using some configuration interface or script (or both). Eventually, modifying and recompiling it yourself is possible if it is open source. Still, the process is usually very complex, and understanding all relations and development toolchain sometimes is more complicated than developing a solution from scratch as a bare metal. Proprietary frameworks do not bring this opportunity at all and are delivered "as is" with a predefined set of features. The development is limited to reconfiguring the elements from simply switching them on and off through setting up access and credentials, | ||
+ | |||
+ | < | ||
+ | |||
+ | The development process for the middleware configuration model is present in the following figure {{ref> | ||
+ | |||
+ | <figure prog_img_middleware> | ||
+ | {{ : | ||
+ | < | ||
+ | </ | ||
+ | |||
+ | Configuration range varies among IoT frameworks but commonly requires compatible hardware. Proprietary firmware provides sealed configuration software and encryption; thus, it virtually excludes any non-standard modifications or makes them very complex. IoT hardware used to be compatible with more than one firmware, and proprietary ones can be replaced with another open source, i.e. Tasmota ((https:// | ||
+ | |||
+ | <table prog_img_middleware> | ||
+ | < | ||
+ | ^ Pros ^ Cons ^ | ||
+ | | Easy to use even for beginners | ||
+ | | Consistent environment (configuration, | ||
+ | | No need for SDK, configuration tools use plain text, browsers or apps | Low flexibility - limited support for hardware (only proprietary or limited compatibility in the case of the open source) | ||
+ | | Manufacturer' | ||
+ | | Usually reliable | ||
+ | | During the maintenance period, updates are given by the vendor | ||
+ | </ | ||
+ | |||
+ | < | ||
+ | ===== Introduction to the Programming Frameworks ===== | ||
+ | In the beginning, it is essential to distinguish an IoT Framework that is a set of tools, firmware for a variety of devices, sometimes also hardware, delivered as is and providing developers with configuration capabilities on the high abstraction level from the Programming Framework that is related to the low-level programming, | ||
+ | This chapter presents and discusses programming frameworks (SDKs and source code organisation) that define how the IoT code is organised on the low level in the Bare Metal programming model for Edge class devices.\\ | ||
+ | |||
+ | Almost every MCU (microchip/ | ||
+ | <code c> | ||
+ | int main() { | ||
+ | std::cout << "Hello IoT!"; | ||
+ | return 0; | ||
+ | } | ||
+ | </ | ||
+ | |||
+ | A common approach is to use a GUI to automate the generation of the source code stub that contains the hardware-specific configuration, | ||
+ | Still, as hardware differs, it is particular for each platform, and usually, software development requires a rigorous approach to inject user-specific code only in predefined locations. Otherwise, it may break source code or even delete it when re-generating configuration using SDK tools and automation. Sample '' | ||
+ | <code c> | ||
+ | int main(void) | ||
+ | { | ||
+ | /* USER CODE BEGIN 1 */ | ||
+ | |||
+ | /* USER CODE END 1 */ | ||
+ | HAL_Init(); | ||
+ | /* USER CODE BEGIN Init */ | ||
+ | |||
+ | /* USER CODE END Init */ | ||
+ | SystemClock_Config(); | ||
+ | /* USER CODE BEGIN SysInit */ | ||
+ | |||
+ | /* USER CODE END SysInit */ | ||
+ | MX_GPIO_Init(); | ||
+ | MX_LPUART1_UART_Init(); | ||
+ | MX_NVIC_Init(); | ||
+ | /* USER CODE BEGIN 2 */ | ||
+ | |||
+ | /* USER CODE END 2 */ | ||
+ | |||
+ | /* Infinite loop */ | ||
+ | /* USER CODE BEGIN WHILE */ | ||
+ | while (1) | ||
+ | { | ||
+ | nUARTBufferLen = sprintf((char*)tUARTBuffer, | ||
+ | HAL_UART_Transmit_IT(& | ||
+ | /* USER CODE END WHILE */ | ||
+ | | ||
+ | /* USER CODE BEGIN 3 */ | ||
+ | } | ||
+ | /* USER CODE END 3 */ | ||
+ | } | ||
+ | </ | ||
+ | |||
+ | Studying specific platforms is time-consuming, | ||
+ | Specific frameworks for hardware vendors are (among others): | ||
+ | * Espressif ESP8266: | ||
+ | * ESP8266 RTOS SDK, | ||
+ | * ESP8266 Non-OS SDK, | ||
+ | * Arduino. | ||
+ | * AVR/Atmel: | ||
+ | * AVR Studio (Atmel Studio), | ||
+ | * Arduino. | ||
+ | * Espressif ESP32: | ||
+ | * ESP-IDF, | ||
+ | * Arduino. | ||
+ | * Nordic Semiconductors nRF52: | ||
+ | * Mbed, | ||
+ | * Zephyr RTOS, | ||
+ | * nRF5 SDK, | ||
+ | * Arduino. | ||
+ | * ST Microelectronics STM32 series: | ||
+ | * Mbed, | ||
+ | * CMSIS, | ||
+ | * Zephyr RTOS, | ||
+ | * Registers programming model (RAW), | ||
+ | * STM32Cube (HAL), | ||
+ | * Arduino. | ||
+ | |||
+ | Typical C++ code, as presented above, is a single-pass execution. On the other hand, IoT devices used to work infinitely, handling their duties such as reading sensors, communicating over the network, sending and receiving data, routing messages and so on, thus, requiring setting up an infinite '' | ||
+ | |||
+ | < | ||
+ | |||
+ | ==== Arduino Framework ==== | ||
+ | Observing the list of software frameworks above, one can easily find that many platforms have common frameworks, but the Arduino framework is present for all of them. Arduino framework is a cross-platform approach providing a slightly higher level of abstraction over dedicated software frameworks, and it is the most popular among hobbyists, students, professionals and even researchers at the moment. Arduino Framework is a reasonable balance between uniform code organisation and elements of cross-hardware HAL, still bringing opportunities to access hardware on a low level and get the advantage of the advanced features of modern IoT microcontrollers such as, e.g. power management. Most hardware vendors support this framework natively, and it has become almost an industry standard. Some advanced hardware control may require integration or other native frameworks, anyway. Still, the Arduino framework has real-time capacity. It is powerful and flexible enough to handle most IoT-related tasks, and most of all, it has excellent community support with dozens of software libraries, examples and applications worldwide. | ||
+ | |||
+ | A dummy C/C++ code for the Arduino framework looks as follows: | ||
+ | <code c> | ||
+ | void setup() | ||
+ | { | ||
+ | |||
+ | } | ||
+ | |||
+ | void loop() | ||
+ | { | ||
+ | |||
+ | } | ||
+ | </ | ||
+ | |||
+ | The '' | ||
+ | The '' | ||
+ | |||
+ | The book presents code and examples in the Arduino framework context for Edge class devices but also for Fog class devices (scripting). Wherever other framework is used, it will be clearly stated. Note, following introduction to the C and C++ programming and task handling contents, are universal and can be applied to the other frameworks, whether directly or indirectly, with some adaptation on the code level. | ||
+ | |||
+ | ===== Software Development Tools and Platforms ===== | ||
+ | Software development in the bare metal model requires a development toolchain installed on the developer' | ||
+ | |||
+ | < | ||
+ | |||
+ | <figure sdt_stm32cubeide> | ||
+ | {{ : | ||
+ | < | ||
+ | </ | ||
+ | |||
+ | Because documentation for the command line tools composing SDK is usually available, there are also universal solutions that enable developers to use a single GUI environment for various tasks and microcontrollers, | ||
+ | |||
+ | <figure sdt_vscode> | ||
+ | {{ : | ||
+ | < | ||
+ | </ | ||
+ | |||
+ | As the Arduino programming framework became a cross-platform standard, vendors provided low-level libraries implementing standard functionalities such as embedded communication protocols (Serial, SPI, I2C, 1Wire) and networking communication. Arduino, a manufacturer of popular development boards, provides an IDE (figure {{ref> | ||
+ | |||
+ | <figure sdt_arduinoide> | ||
+ | {{ : | ||
+ | < | ||
+ | </ | ||
+ | <note tip>We suggest starting with VS Code and PlatformIO over Arduino IDE, even if you're a beginner.</ | ||
+ | |||
+ | ==== Developers Middleware and Support Tools ==== | ||
+ | A number of additional tools usually come with the development toolchain provided by the hardware vendors. They include programmers (flashers, injecting firmware into the IoT device), configuration tools, power consumption calculators, | ||
+ | |||
+ | |||
+ | === PlatformIO === | ||
+ | {{: | ||
+ | |||
+ | <figure std_pio1> | ||
+ | {{ : | ||
+ | < | ||
+ | </ | ||
+ | |||
+ | <figure std_pio2> | ||
+ | {{ : | ||
+ | < | ||
+ | </ | ||
+ | |||
+ | <figure std_pio3> | ||
+ | {{ : | ||
+ | < | ||
+ | </ | ||
+ | |||
+ | A PlatformIO-enabled IoT project is a set of files with a '' | ||
+ | <code ini> | ||
+ | [env: | ||
+ | platform = espressif8266 | ||
+ | board = d1_mini | ||
+ | framework = arduino | ||
+ | upload_port = / | ||
+ | upload_speed = 9600 | ||
+ | monitor_port = / | ||
+ | lib_deps = | ||
+ | arduino-libraries/ | ||
+ | adafruit/ | ||
+ | adafruit/ | ||
+ | </ | ||
+ | This code configures the ESP8266 (Espressif) hardware project, with specific developer board D1 Mini and programming done in the " | ||
+ | Communication with the IoT device is via serial port (here ''/ | ||
+ | At the start of the PlatformIO GUI and then periodically, | ||
+ | |||
+ | ===== C/C++ Language Embedded Programming Fundamentals ===== | ||
+ | |||
+ | The following sub-chapters cover programming fundamentals in C/C++, which comply with most C/C++ notations. | ||
+ | Those who feel comfortable in programming will find these chapters somewhat introductory, | ||
+ | |||
+ | <note tip>This manual refers to the particular versions of the software available at the moment of writing this book. Accessing specific features may change over time along with the evolution of the platform. Please refer to the attached documentation (if any) and browse Internet resources to find the latest guidance on configuring specific development platforms when in doubt.</ | ||
+ | |||
+ | ==== Data Types and Variables ==== | ||
+ | Almost every computer program manipulates the data. Data representation in the program is variable. In C/C++, the variable needs to be defined before using it, giving it some name and assigning chosen type, dependent on the kind of data. Here we show some common data types and how to use variables. | ||
+ | |||
+ | === Data Types === | ||
+ | Data type specifies how it is encoded and represented in the computer memory. For example, integer numbers are binary-encoded, | ||
+ | |||
+ | * **// | ||
+ | |||
+ | <code c> | ||
+ | byte exampleVariable; | ||
+ | </ | ||
+ | |||
+ | The example above defines a variable, reserves its memory, and assigns the memory address to the variable name. It is also possible to give the variable the initial value as below: | ||
+ | |||
+ | <code c> | ||
+ | byte exampleVariable = 123; | ||
+ | </ | ||
+ | |||
+ | * **//int//** – the integer number. Its size depends on the microcontroller class. In the case of AVR (Arduino), it consists of 16 bits that can contain values from –32 767 to 32 768. In ARM-based microcontrollers (like STM32), its size is 32 bits. | ||
+ | |||
+ | <code c> | ||
+ | int exampleVariable = 12300; | ||
+ | </ | ||
+ | |||
+ | * **// | ||
+ | |||
+ | <code c> | ||
+ | float exampleVariable = 12300.546; | ||
+ | </ | ||
+ | |||
+ | * **// | ||
+ | |||
+ | <code c> | ||
+ | int firstArray[] = {12, | ||
+ | </ | ||
+ | |||
+ | Square brackets of the array can be used to access some value in the array by index. In the following example, the element with index 1 (that is –3) is assigned to the // | ||
+ | |||
+ | <code c> | ||
+ | int secondVariable = firstArray[1]; | ||
+ | </ | ||
+ | |||
+ | An array can be quickly processed in the loop. The following example shows how to calculate the sum of all elements from the previously defined array (//for// statement will be explained in detail in the following chapters). | ||
+ | |||
+ | <code c> | ||
+ | //The loop that repeats 4 times | ||
+ | int sum = 0; | ||
+ | for(int i = 0; i < 4; i = i + 1){ | ||
+ | sum = sum + firstArray[i]; | ||
+ | } | ||
+ | </ | ||
+ | |||
+ | The loop in the example starts with index 0 (//i// = 0) and increases it by 1 while smaller than 4 (not including). That means the index value will be 3 in the last cycle because when the //i// equals 4, the inequality //i// < 4 is not true, and the loop stops working. | ||
+ | |||
+ | * **// | ||
+ | |||
+ | |||
+ | === Data Type Conversion === | ||
+ | Data type conversion can be done using multiple techniques – casting or data type conversion using specific functions. | ||
+ | |||
+ | * **Casting** – cast operator translates one data type into another type straight forward. The desired variable type should be written in the brackets before the variable data type, which needs to be changed. In the following example, where the variable type is changed from float to int, the value is not rounded but truncated. Casting can be done to any variable type. | ||
+ | |||
+ | <code c> | ||
+ | int i; | ||
+ | float f=4.7; | ||
+ | |||
+ | i = (int) f; //Now it is 4 | ||
+ | </ | ||
+ | |||
+ | * **Converting** – //byte(), char(), int(), long(), word(), float()// functions are used to convert any type of variable to the specified data type. | ||
+ | |||
+ | <code c> | ||
+ | int i = int(123.45); | ||
+ | </ | ||
+ | |||
+ | * **Converting //String// to //float//** – function // | ||
+ | |||
+ | <code c> | ||
+ | String string = " | ||
+ | float f = string.toFLoat(); | ||
+ | </ | ||
+ | |||
+ | * **Converting //String// to //Int//** – function //toInt()// converts //String// type of variable to the //Int//. In the following example, the use of this function is shown. | ||
+ | |||
+ | <code c> | ||
+ | String string = " | ||
+ | int i = string.toInt(); | ||
+ | </ | ||
+ | |||
+ | === Defining New Types === | ||
+ | |||
+ | == Typedef Specifier == | ||
+ | A '' | ||
+ | <code c> | ||
+ | typedef struct {int x; int y;} tWaypoint; //Declare complex type named waypoint | ||
+ | ... | ||
+ | //Declare a variable of the type of tWaypoint | ||
+ | tWaypoint wp1; | ||
+ | </ | ||
+ | |||
+ | == Enum Declaration == | ||
+ | Enumerations are helpful to give meaning to the integer values and present some logic in a code instead of putting numbers into it. It can be, i.e., the device' | ||
+ | In the case a new enumeration is needed, it is possible to declare one using the '' | ||
+ | <code c> | ||
+ | enum errorcodes {ER_OK, ER_DOWNLOAD, | ||
+ | ... | ||
+ | errorcodes Errorcode; | ||
+ | ... | ||
+ | Errorcode = ER_DOWNLOAD; | ||
+ | </ | ||
+ | The default numbering starts with 0 ('' | ||
+ | <code c> | ||
+ | enum errorcodes {ER_OK=0, ER_DOWNLOAD=3, | ||
+ | </ | ||
+ | ==== Operators, Specifiers and Pointers ==== | ||
+ | |||
+ | Operators represent mathematical, | ||
+ | |||
+ | === Assignment Operator === | ||
+ | |||
+ | * **Assignment operator ( = )** – the operator that assigns the value on the right to the variable on the assignment operator' | ||
+ | |||
+ | === Arithmetic Operators === | ||
+ | |||
+ | Arithmetic operations are used to do mathematical calculations with numbers or numerical variables. The arithmetic operators are the following. | ||
+ | * **Addition ( + )** – one of the four primary arithmetic operations used to add numbers. The addition operator can add only numbers, numeric variables, or a mix of both. The following example shows the use of the addition operator. | ||
+ | <code c> | ||
+ | int result = 1 + 2; //The result of the addition operation will be 3 | ||
+ | </ | ||
+ | * **Subtraction ( - )** – the operation that subtracts one number from another where the result is the difference between these numbers. | ||
+ | <code c> | ||
+ | int result = 3 - 2; //The result of the subtraction operation will be 1 | ||
+ | </ | ||
+ | * **Multiplication ( * )** – the operation that multiplies numbers and gives the result. | ||
+ | <code c> | ||
+ | int result = 2 * 3; //The result of the multiplication operation will be 6 | ||
+ | </ | ||
+ | * **Division ( / )** – the operation that divides one number by another. If the result variable has the //integer// type, the result will always be the whole part of the division result without the fraction behind it. If the precise division is necessary, using the //float// type of variable for this purpose is important. | ||
+ | <code c> | ||
+ | //The result of the division operation will be 3 | ||
+ | //(Only the whole part of the division result) | ||
+ | int result = 7 / 2; | ||
+ | //The result of the division operation will be 3.5 | ||
+ | float result2 = 7.0 / 2.0; | ||
+ | </ | ||
+ | * **Modulo ( % )** – the operation that finds the remainder of the division of two numbers. | ||
+ | <code c> | ||
+ | //The result of the modulo operation will be 1, | ||
+ | //Because if 7 is divided by 3, the remaining is 1 | ||
+ | int result = 7 % 3; | ||
+ | </ | ||
+ | |||
+ | === Bitwise Operators === | ||
+ | |||
+ | Bitwise operators perform operations on bits in the variable. Among them, there exist bitwise logic operations. It means the same logic function is applied to every pair of bits in two arguments. Bitwise or ( | ) means that if at least one bit is " | ||
+ | |||
+ | <code c> | ||
+ | byte result = 5 | 8; | ||
+ | ; //The operation in numbers gives the result of 13 | ||
+ | ; //in bits can be shown as follows | ||
+ | ; // 00000101b | ||
+ | ; // 00001000b | ||
+ | ; // --------- | ||
+ | ; // 00001101b | ||
+ | </ | ||
+ | |||
+ | <code c> | ||
+ | byte result = 5 & 1; | ||
+ | ; //The operation in numbers gives the result of 1 | ||
+ | ; //in bits can be shown as follows | ||
+ | ; // 00000101b | ||
+ | ; // 00000001b | ||
+ | ; // --------- | ||
+ | ; // 00000001b | ||
+ | </ | ||
+ | |||
+ | Bitwise operators also allow shifting data left ( << ) or right ( >> ) chosen number of bit positions. Shifting is often used in embedded programming to access the bit at a specific position. Shifting data one bit left gives the result of multiplication by 2 while shifting one bit right gives the effect of dividing by 2. | ||
+ | |||
+ | <code c> | ||
+ | byte result = 5 << 1; | ||
+ | ; //The operation in numbers gives the result of 10 | ||
+ | ; //in bits can be shown as follows | ||
+ | ; // 00000101b | ||
+ | ; // 00001010b | ||
+ | </ | ||
+ | |||
+ | === Compound Operators === | ||
+ | |||
+ | Compound operators in C/C++ are a short way of writing down the arithmetic operations with variables. All of these operations are done on integer variables. These operands are often used in the loops when it is necessary to manipulate the same variable in each cycle iteration. The compound operators are the following. | ||
+ | * **Increment ( ++ )** – increases the value of integer variable by one. | ||
+ | <code c> | ||
+ | int a = 5; | ||
+ | a++; //The operation a = a + 1; the result will be 6 | ||
+ | </ | ||
+ | * **Decrement ( - - )** – decreases the value of the integer variable by one. | ||
+ | <code c> | ||
+ | int a = 5; | ||
+ | a--; //The operation a = a – 1; the result will be 4 | ||
+ | </ | ||
+ | * **Compound addition ( += )** – adds the right operand to the left operand and assigns the result to the left operand. | ||
+ | <code c> | ||
+ | int a = 5; | ||
+ | a+=2; //The operation a = a + 2; the result will be 7 | ||
+ | </ | ||
+ | * **Compound subtraction ( -= )** – subtracts the right operand from the left operand and assigns the result to the left operand. | ||
+ | <code c> | ||
+ | int a = 5; | ||
+ | a-=3; //The operation a = a – 3; the result will be 2 | ||
+ | </ | ||
+ | * **Compound multiplication ( *= )** – multiplies the left operand by the right operand and assigns the result to the left operand. | ||
+ | <code c> | ||
+ | int a = 5; | ||
+ | a*=3; //The operation a = a × 3; the result will be 15 | ||
+ | </ | ||
+ | * **Compound division ( /= )** – divides the left operand with the right operand and assigns the result to the left operand. | ||
+ | <code c> | ||
+ | int a = 6; | ||
+ | a/=3; //The operation a = a / 3; the result will be 2 | ||
+ | </ | ||
+ | * **Compound modulo ( %= )** – takes modulus using two operands and assigns the result to the left operand. | ||
+ | <code c> | ||
+ | int a = 5; | ||
+ | //The result will be the remaining | ||
+ | //Part of the operation a/2; it results in 1 | ||
+ | a%=2; | ||
+ | </ | ||
+ | * **Compound bitwise //OR// ( |= )** – bitwise //OR// operator that assigns the value to the operand on the left. | ||
+ | <code c> | ||
+ | int a = 5; | ||
+ | a|=2; //The operation a=a|2; the result will be 7 | ||
+ | </ | ||
+ | * **Compound bitwise //AND// ( &= )** – bitwise //AND// operator that assigns the value to the operand on the left. | ||
+ | <code c> | ||
+ | int a = 6; | ||
+ | a&=; //The operation a=a&2; the result will be 2 | ||
+ | </ | ||
+ | |||
+ | === & and * Operators: Pointers and References === | ||
+ | Simple and complex types can be referred to with the use of pointer variables. A pointer is a variable that holds the address of the variable. The length of the pointer is equivalent to the length of the memory address (usually 16, 32 or 64 bits). A pointer does not contain a value but rather points to the variable (a memory) where the value is stored. A pointer variable must be initialised and dereferenced with Address-Of and Dereferencing operators.\\ | ||
+ | The following example presents a simple type declaration and the use of a pointer variable. | ||
+ | |||
+ | ''&'' | ||
+ | '' | ||
+ | |||
+ | <code c> | ||
+ | int n = 10; // | ||
+ | int *ptr; // | ||
+ | //At this point, *ptr does not contain any address yet, | ||
+ | //rather some random address or null. | ||
+ | ptr = & | ||
+ | //ptr contains now an address of the memory where variable n is located, | ||
+ | //not a value 10 | ||
+ | int k; //Declare another variable | ||
+ | k = *ptr; // | ||
+ | </ | ||
+ | Simple type variables such as '' | ||
+ | The importance of pointers is not to be underestimated in this case: you simply declare a pointer pointing to the array' | ||
+ | |||
+ | |||
+ | ==== Program Control Statements, Logical operators ==== | ||
+ | |||
+ | It is essential to understand that if no statements change the normal program flow, the microcontroller executes instructions one by one in the order they appear in the source code (from the top - to the down direction). Control statements modify normal program flow by skipping or repeating parts of the code. Often to decide if the part of the code should be executed or to choose one of the number of possible execution paths, conditional statements are used. For repeating the part of the code, loop statements can be used. | ||
+ | |||
+ | === Conditional Statement === | ||
+ | //**if**// is a statement that checks the condition and executes the following statement if the condition is //TRUE//. There are multiple ways how to write down the //**if**// statement: | ||
+ | |||
+ | <code c> | ||
+ | //1st example | ||
+ | if (condition) statement; | ||
+ | |||
+ | //2nd example | ||
+ | if (condition) | ||
+ | statement; | ||
+ | |||
+ | //3rd example | ||
+ | if (condition) { statement; } | ||
+ | |||
+ | //4th example | ||
+ | if (condition) | ||
+ | { | ||
+ | statement; | ||
+ | } | ||
+ | </ | ||
+ | |||
+ | The version with curly braces is used when there is a need to execute part of the code that consists of more than a single statement. Many statements taken together with pair of curly braces are treated as a single statement in such cases. | ||
+ | When both //TRUE// and //FALSE// cases of the condition should be viewed, the // | ||
+ | |||
+ | <code c> | ||
+ | if (condition) { | ||
+ | statement1; | ||
+ | } | ||
+ | else { | ||
+ | statement2; | ||
+ | } | ||
+ | </ | ||
+ | |||
+ | If more conditions should be viewed, the //**else if**// part is added to the //**if**// statement: | ||
+ | <code c> | ||
+ | if (condition1) { | ||
+ | statement1; | ||
+ | } | ||
+ | else if (condition2) { | ||
+ | statement2; | ||
+ | } | ||
+ | else { | ||
+ | statement3; | ||
+ | } | ||
+ | </ | ||
+ | |||
+ | For example, when the //x// variable is compared and when it is higher than 10, the // | ||
+ | <code c> | ||
+ | if (x> | ||
+ | { | ||
+ | //Statement is executed if the x > 10 expression is true | ||
+ | digitalWrite(LEDpin, | ||
+ | } | ||
+ | </ | ||
+ | |||
+ | |||
+ | === Logical Operators === | ||
+ | To allow checking different conditions, logical operators are widely used with the condition statement //**if**// described above. | ||
+ | |||
+ | **Comparison Operators** | ||
+ | |||
+ | There are multiple comparison operators used for comparing variables and values. All of these operators compare the variable' | ||
+ | * == (equal to) – if they are equal, the result is //TRUE//, otherwise //FALSE//; | ||
+ | * != (not equal to) – if they are not equal, the result is //TRUE//, otherwise //FALSE//; | ||
+ | * < (less than) – if the value of the variable on the left is less than the value of the variable on the right, the result is //TRUE//, otherwise //FALSE//; | ||
+ | * < = (less than or equal to) – if the value of the variable on the left is less than or equal to the value of the variable on the right, the result is //TRUE//, otherwise //FALSE//; | ||
+ | * > (greater than) – if the value of the variable on the left is greater than the value of the variable on the right, the result is //TRUE//, otherwise //FALSE//; | ||
+ | * > = (greater than or equal to) – if the value of the variable on the left is greater than or equal to the value of the variable on the right, the result is //TRUE//, otherwise //FALSE//. | ||
+ | |||
+ | Examples: | ||
+ | <code c> | ||
+ | if (x==y){ //Equal | ||
+ | //Statement | ||
+ | } | ||
+ | |||
+ | if (x!=y){ //Not equal | ||
+ | //Statement | ||
+ | } | ||
+ | |||
+ | if (x<y){ //Less than | ||
+ | //Statement | ||
+ | } | ||
+ | |||
+ | if (x<=y){ //Less than or equal | ||
+ | //statement | ||
+ | } | ||
+ | |||
+ | if (x>y){ //Greater than | ||
+ | //Statement | ||
+ | } | ||
+ | |||
+ | if (x>=y){ //Greater than or equal | ||
+ | //Statement | ||
+ | } | ||
+ | </ | ||
+ | |||
+ | **Boolean Operators** | ||
+ | |||
+ | The Boolean logical operators in C/C++ are the following: | ||
+ | * ! (logical //NOT//) – reverses the logical state of the operand. If a condition is //TRUE// the logical NOT operator will turn it to //FALSE// and the other way around; | ||
+ | * && (logical //AND//) – the result is //TRUE// when both operands on the operator' | ||
+ | * || (logical //OR//) – the result is //TRUE// when at least one of the operands on the left and on the right of the operator is //TRUE//. If both of them are //FALSE//, the result is //FALSE//. | ||
+ | |||
+ | Examples: | ||
+ | <code c> | ||
+ | //Logical NOT | ||
+ | if (!a) { //The statement inside if will execute when the a is FALSE | ||
+ | b = !a; //The reverse logical value of a is assigned to the variable b | ||
+ | } | ||
+ | |||
+ | //Logical AND | ||
+ | //The statement inside if will execute when the | ||
+ | //Values both of the a and b are TRUE | ||
+ | if (a && b){ | ||
+ | //Statement | ||
+ | } | ||
+ | |||
+ | //Logical OR | ||
+ | //The statement inside if will execute when at least one of the | ||
+ | //a and b values are TRUE | ||
+ | if (a || b){ | ||
+ | //Statement | ||
+ | } | ||
+ | </ | ||
+ | |||
+ | === Switch Case Statement === | ||
+ | A switch statement similar to the //if// statement controls the flow of a program. The code inside //switch// is executed in various conditions. A //switch// statement compares the values of a variable to the specified values in the //case// statements. Allowed data types of the variable are //int// and //char//. The //break// keyword exits the //switch// statement. | ||
+ | |||
+ | Examples: | ||
+ | <code c> | ||
+ | switch (x) { | ||
+ | case 0: //Executes when the value of x is 0 | ||
+ | // statements | ||
+ | | ||
+ | |||
+ | case 1: //Executes when the value of x is 1 | ||
+ | // statements | ||
+ | | ||
+ | |||
+ | | ||
+ | // statements | ||
+ | | ||
+ | } | ||
+ | </ | ||
+ | |||
+ | |||
+ | **Check Yourself** | ||
+ | |||
+ | 1. Which code part is the correct one? | ||
+ | |||
+ | * if(value == 1) digitalWrite(13, | ||
+ | * if (value == 1); digitalWrite(13, | ||
+ | * if (value == 1) DigitalRead(13, | ||
+ | 2. What is the output of the next code part? | ||
+ | |||
+ | <code c> | ||
+ | int x = 0; | ||
+ | |||
+ | switch(x) | ||
+ | { | ||
+ | |||
+ | case 1: cout << " | ||
+ | |||
+ | case 0: cout << " | ||
+ | |||
+ | case 2: cout << " | ||
+ | |||
+ | } | ||
+ | </ | ||
+ | 3. In which case should the// | ||
+ | ==== Loops ==== | ||
+ | |||
+ | Loops are critical to control flow structures in programming. They allow executing statements or some part of the program repeatedly to process elements of data tables and texts, making iterative calculations and data analysis. In the world of microcontrollers, | ||
+ | |||
+ | === for === | ||
+ | **//for//** is a loop statement that allows specifying the number of times of execution statements inside it. Each time all statements in the loop's body are executed is called an **iteration**. In this way, the loop is one of the basic programming techniques used for all programs and automation in general. | ||
+ | |||
+ | The construction of a //for// loop is the following: | ||
+ | <code c> | ||
+ | for (initialization ; condition ; operation with the cycle variable) { | ||
+ | //The body of the loop | ||
+ | } | ||
+ | </ | ||
+ | |||
+ | Three parts of the //for// construction are the following: | ||
+ | * ** initialisation** section usually initialises the value of the cycle variable that will be used to iterate the loop; the initialisation value is ofter 0 but can be any other value; | ||
+ | * **condition** allows managing the number of loop iterations; the statements in the body of the loop are executed when the condition is //TRUE//; | ||
+ | * **operation with the cycle variable** specifies how the cycle variable is modified every iteration (incremented, | ||
+ | |||
+ | The example of the //for// loop: | ||
+ | <code c> | ||
+ | for (int i = 0; i < 4; i = i + 1) | ||
+ | { | ||
+ | digitalWrite(13, | ||
+ | delay(1000); | ||
+ | digitalWrite(13, | ||
+ | delay(1000); | ||
+ | } | ||
+ | </ | ||
+ | On the initialisation of the //for// loop, the cycle variable //i// = 0 is defined. The condition states that the //for// loop will be executed while the variable //i// value will be less than 4 (//i// < 4). In operation with the cycle variable, it is increased by 1 each time when the loop is repeated. | ||
+ | |||
+ | In the example above, Arduino function digitalWrite is used. It sets the logical state high or low at the chosen pin. If a LED is connected to pin 13 of the Arduino board, it will turn on/off four times. | ||
+ | |||
+ | === while === | ||
+ | **// | ||
+ | |||
+ | The construction of the //while// loop is the following: | ||
+ | <code c> | ||
+ | while (condition is TRUE) | ||
+ | { | ||
+ | //The body of the loop | ||
+ | } | ||
+ | </ | ||
+ | |||
+ | That way, the //while// loop can be used as a good instrument for the execution of a previously unpredictable program. For example, if it is necessary to wait until the signal from pin 2 reaches the defined voltage level = 100, the following code can be used: | ||
+ | |||
+ | <code c> | ||
+ | int inputVariable = analogRead(2); | ||
+ | while (inputVariable < 100) | ||
+ | { | ||
+ | digitalWrite(13, | ||
+ | delay(10); | ||
+ | digitalWrite(13, | ||
+ | delay(10); | ||
+ | inputVariable = analogRead(2); | ||
+ | } | ||
+ | </ | ||
+ | |||
+ | In the loop above, the LED that is connected to pin 13 of the Arduino board will be turned on/off until the signal reaches the specified level. | ||
+ | |||
+ | === do...while === | ||
+ | The // | ||
+ | |||
+ | The construction of a //do while// loop is the following: | ||
+ | <code c> | ||
+ | do { | ||
+ | //The body of the loop | ||
+ | } while (a condition that is TRUE); | ||
+ | </ | ||
+ | |||
+ | If the same code is taken from the //while// loop example and used in the // | ||
+ | <code c> | ||
+ | int inputVariable = analogRead(2); | ||
+ | do { | ||
+ | digitalWrite(13, | ||
+ | delay(10); | ||
+ | digitalWrite(13, | ||
+ | delay(10); | ||
+ | inputVariable = analogRead(2); | ||
+ | } while (inputVariable < 100); | ||
+ | </ | ||
+ | ==== Sub-programs, | ||
+ | |||
+ | In many cases, the program grows to a size that becomes hardly manageable as a single unit. It is quite difficult to navigate through the code that occupies many screens. In such a situation, subprograms can help. Subprograms are named functions in C, and in C++, while they are associated with an object, they are named methods (in this chapter, the name // function // will be used). The function contains a set of statements that usually form some logical part of the code that can be separately tested and verified, making the whole program easy to manage. It is possible to group many functions by creating a library that is stored in a separate file. This is how external libraries are created. | ||
+ | |||
+ | === Functions === | ||
+ | Functions are the set of statements that are always executed when the function is called. A function can accept arguments as its input data and return the resulting value. | ||
+ | Two functions from the Arduino programming model that were mentioned before are already known – //setup()// and //loop()//. The programmer usually tries to make several functions containing all the statements and then calls them in the //setup()// or //loop()// functions. | ||
+ | |||
+ | The structure of the function is following: | ||
+ | <code c> | ||
+ | type functionName(arguments) //A return type, name, and arguments of the function | ||
+ | { | ||
+ | //The body of a function – statements to execute | ||
+ | } | ||
+ | </ | ||
+ | |||
+ | For example, a function that periodically turns on and off the LED can look like this: | ||
+ | |||
+ | <code c> | ||
+ | void exampleFunction() | ||
+ | { | ||
+ | digitalWrite(13, | ||
+ | delay(1000); | ||
+ | digitalWrite(13, | ||
+ | delay(1000); | ||
+ | } | ||
+ | </ | ||
+ | |||
+ | The example above shows that the return type of a// | ||
+ | |||
+ | This function should be called inside the //loop()// function in the following way: | ||
+ | |||
+ | <code c> | ||
+ | void loop() | ||
+ | { | ||
+ | exampleFunction(); | ||
+ | } | ||
+ | </ | ||
+ | |||
+ | The whole code in the Arduino environment looks like this: | ||
+ | |||
+ | <code c> | ||
+ | void loop() | ||
+ | { | ||
+ | exampleFunction(); | ||
+ | } | ||
+ | |||
+ | void exampleFunction() | ||
+ | { | ||
+ | digitalWrite(13, | ||
+ | delay(1000); | ||
+ | digitalWrite(13, | ||
+ | delay(1000); | ||
+ | } | ||
+ | </ | ||
+ | |||
+ | It can be seen that the function is defined outside the //loop()// or //setup()// functions. | ||
+ | |||
+ | When some specific result must be returned as a result of a function, then the function return type should be indicated, for example: | ||
+ | |||
+ | <code c> | ||
+ | //the return type is " | ||
+ | int sumOfTwoNumbers(int x, int y) | ||
+ | { | ||
+ | //the value next to the " | ||
+ | //this is what will be returned as a result. | ||
+ | return (x+y); | ||
+ | } | ||
+ | </ | ||
+ | |||
+ | In the //loop()//, this function would be called in the following way: | ||
+ | <code c> | ||
+ | void loop() | ||
+ | { | ||
+ | //the call of the defined function inside the loop() | ||
+ | int result = sumOfTwoNumbers(2, | ||
+ | } | ||
+ | </ | ||
+ | |||
+ | === Built-in functions === | ||
+ | Every programming SDK, including Arduino IDE, comes with several ready-made functions that help develop applications, | ||
+ | |||
+ | === Library functions === | ||
+ | The popularity of microcontrollers and embedded programming caused the growth of communities of enthusiasts who create a vast of useful software. This usually comes in the form of a set of functions created to handle some specific tasks, e.g. interfacing with a family of graphical displays or communicating using the chosen protocol. Functions created for one purpose are grouped together, forming the library. The number of libraries and their different version is so big that software developers use a special library manager to ensure that libraries are up-to-date or keep them in stable versions. | ||
+ | |||
+ | === Function handlers === | ||
+ | In the MCU world, is is common to use libraries that require a user (software developer) to implement a specific part of the code that is later automatically called by the library routines. Those functions are frequently called handlers and enable developers to inject their actions for a predefined set of activities without needing to modify library code. For this reason, the library contains a placeholder variable that can be assigned an executable code (a function body). Obviously, this is handled with the use of pointers. | ||
+ | A sample function handler variable is presented in the following code, along with the user function definition, assignment to the handler variable and a call to the handler: | ||
+ | <code c> | ||
+ | int (*hUserImplementedFunction)(int); | ||
+ | //(no code is here; it is just a pointer to the code, | ||
+ | //currently NULL, pointing to " | ||
+ | ... | ||
+ | int fMulx2(int a) { // | ||
+ | return (2*a); | ||
+ | } // | ||
+ | ... | ||
+ | hUserImplementedFunction = fMulx2; | ||
+ | //starting from now, hUserImplementedFunction contains an address of the | ||
+ | //fMulx2 function | ||
+ | ... | ||
+ | int j; | ||
+ | if (hUserImplementedFunction!=NULL) | ||
+ | j = hUserImplementedFunction(10); | ||
+ | |||
+ | </ | ||
+ | <note important> | ||
+ | <note tip> | ||
+ | ==== Structures and Classes ==== | ||
+ | Structures and classes present complex data types, definable by the developer. Not all C/C++ programming environments provide support for classes (i.e., STM32 in HAL framework mode does not), but luckily, the Arduino framework supports it. Structures, conversely, are part of the C language definition and are present in almost every implementation of software frameworks for IoT microcontrollers. | ||
+ | |||
+ | === Structures === | ||
+ | |||
+ | In C and C++, a structure is a user-defined data type that allows you to combine different types of variables under a single name. | ||
+ | A structure primarily groups related variables, forming a complex data type. A custom data structure (type) that can hold multiple variables, each with its own data type. These variables, called members or fields, can be of any built-in or user-defined type, including other structures. | ||
+ | The sample named structure (equivalent to the complex type), variable declaration and use of member fields are presented below: | ||
+ | <code c> | ||
+ | struct address { | ||
+ | String city; | ||
+ | String PO; | ||
+ | String street; | ||
+ | double longitude; | ||
+ | double latitude; | ||
+ | }; | ||
+ | ... | ||
+ | address adr1; | ||
+ | </ | ||
+ | |||
+ | Note it is also possible to declare a structure variable directly without defining a type: | ||
+ | <code c> | ||
+ | struct { | ||
+ | String city; | ||
+ | String PO; | ||
+ | String street; | ||
+ | double longitude; | ||
+ | double latitude; | ||
+ | } adr2, adr3; | ||
+ | </ | ||
+ | |||
+ | Structures with type definitions are common when authoring libraries to let library users be able to declare new variables on their own, simply using a type. | ||
+ | |||
+ | == Manipulating Structure' | ||
+ | Access to the fields of the structure' | ||
+ | <code c> | ||
+ | adr1.city = " | ||
+ | adr2.city = " | ||
+ | adr3.street = " | ||
+ | </ | ||
+ | The structure' | ||
+ | <code c> | ||
+ | adr3 = {" | ||
+ | </ | ||
+ | In C++, structures can also have member functions that manipulate the data (in C, they cannot). That is not so far from the Classes idea described in the following chapter. | ||
+ | In the case of using C (or poor implementation of C++ that does not support classes nor member functions, i.e. STM32), it is common to prepare a set of data handling functions that operate on the structure referenced with a pointer. A common rule of thumb is the structure is the first argument in the function: | ||
+ | <code c> | ||
+ | struct calcdata | ||
+ | { | ||
+ | double x,y; | ||
+ | } args; | ||
+ | |||
+ | //Adds x and y of the " | ||
+ | double fCalcDataAdd(calcdata *arguments){ | ||
+ | return (arguments-> | ||
+ | } | ||
+ | //Multilies x and y of the " | ||
+ | double fCalcDataMul(calcdata *arguments){ | ||
+ | return ((arguments-> | ||
+ | } | ||
+ | //Sets x and y of the " | ||
+ | void fCalcDataSet(calcdata *arguments, double px, double py){ | ||
+ | arguments-> | ||
+ | arguments-> | ||
+ | } | ||
+ | </ | ||
+ | In the examples above, we use a " | ||
+ | |||
+ | Sample use of the functions is then: | ||
+ | <code c> | ||
+ | args = {2, | ||
+ | fCalcDataSet(& | ||
+ | int z = fCalcDataAdd(& | ||
+ | </ | ||
+ | === Classes === | ||
+ | Classes were introduced in C++ to extend structures encapsulating data and methods (functions) to process this data. A method presented above in the structure context brings an overhead with a need to pass a pointer to the structure for each call. Moreover, it makes access levels tricky, i.e. when you do not want to expose some functions but rather use them for internal data processing. Thus classes can be considered as an extension of the structures.\\ | ||
+ | < | ||
+ | <note important> | ||
+ | Sample class definition is presented below: | ||
+ | <code c> | ||
+ | class Calculator | ||
+ | { | ||
+ | public: //you can access this part | ||
+ | int x,y; | ||
+ | Calculator() { //Default constructor | ||
+ | clear(); | ||
+ | } | ||
+ | Calculator(int px, int py) { //Another constructor | ||
+ | x=px; | ||
+ | y=py; | ||
+ | } | ||
+ | ~Calculator(){} //This is dummy destructor | ||
+ | int Add(){ return x+y; } | ||
+ | int Mul(){ return x*y; } | ||
+ | void setX(int px){ x=px; } | ||
+ | void setY(int py){ y=py; } | ||
+ | private: //that part is private, and you cannot access it | ||
+ | void clear(){ | ||
+ | x=0; y=0; | ||
+ | } | ||
+ | }; | ||
+ | </ | ||
+ | The code above declares a new type, '' | ||
+ | **Constructors**\\ | ||
+ | There are " | ||
+ | <code c> | ||
+ | Calculator calc1=Calculator(2, | ||
+ | </ | ||
+ | The above code instantiates an object '' | ||
+ | There can be multiple constructors, | ||
+ | **Destructor**\\ | ||
+ | A destructor is called automatically when an object' | ||
+ | <code c> | ||
+ | ~Calculator(){} //This is dummy destructor | ||
+ | </ | ||
+ | <note tip>In the embedded world, explicitly implemented destructors releasing allocated memory are rare as for the safety of the software, dynamic allocation of the memory is rather to be avoided; thus, destructors are eventually related to the network connections more than memory management.</ | ||
+ | **Members**\\ | ||
+ | Member fields can be of any type. When marked as '' | ||
+ | **Methods**\\ | ||
+ | A method can have any name other than reserved (i.e. for constructors and destructor). Methods marked as '' | ||
+ | <code c> | ||
+ | // | ||
+ | int z = calc1.Add(); | ||
+ | calc1.setX(10); | ||
+ | calc1.setY(20); | ||
+ | z = calc1.Mul(); | ||
+ | </ | ||
+ | |||
+ | **Class inheritance**\\ | ||
+ | Classes can be inherited. This mechanism enables the real power of C++, where existing models (classes) can be extended with new logic without a need to rewrite and fork existing source code. In the example above, the '' | ||
+ | A code below defines a new type '' | ||
+ | <code c> | ||
+ | class BetterCalculator: | ||
+ | { | ||
+ | public: | ||
+ | BetterCalculator() { | ||
+ | } | ||
+ | BetterCalculator(int px, int py): | ||
+ | } | ||
+ | int Sub(){return x-y;} | ||
+ | }; | ||
+ | </ | ||
+ | Members '' | ||
+ | Instantiation and use are similar to the presented ones in the previous examples: | ||
+ | <code c> | ||
+ | BetterCalculator calc2=BetterCalculator(10, | ||
+ | ... | ||
+ | z = calc2.Sub(); | ||
+ | z = calc2.Add(); | ||
+ | // | ||
+ | </ | ||
+ | The description above does not deplete all features of C++ Object Oriented Programming. Please note, however, that in the case of the embedded C++, their implementation can be limited and may not contain all the features of the modern, standard C++ patterns. | ||
+ | |||
+ | **A special note on the libraries with separate definition (header) and implementation (body)**\\ | ||
+ | Many libraries come with a class definition in the header file (.h) and its implementation in the code file (.cpp). This is convenient for separating use patterns and implementations. A special operator, "::" | ||
+ | The sample header file '' | ||
+ | <code c> | ||
+ | #ifndef h_MYCLASS | ||
+ | #define h_MYCLASS | ||
+ | class Calculator{ | ||
+ | public: //you can access this part | ||
+ | int x,y; | ||
+ | Calculator(); | ||
+ | Calculator(int px, int py); //Another constructor | ||
+ | ~Calculator(); | ||
+ | int Add(); | ||
+ | int Mul(); | ||
+ | void setX(int px); | ||
+ | void setY(int py); | ||
+ | private: //that part is private, and you cannot access it | ||
+ | void clear(); | ||
+ | }; | ||
+ | #endif | ||
+ | </ | ||
+ | The implementation code refers to the class definition in the header: | ||
+ | <code c> | ||
+ | #include " | ||
+ | |||
+ | Calculator:: | ||
+ | Calculator:: | ||
+ | Calculator:: | ||
+ | int Calculator:: | ||
+ | int Calculator:: | ||
+ | void Calculator:: | ||
+ | void Calculator:: | ||
+ | void Calculator:: | ||
+ | </ | ||
+ | ==== Timing ==== | ||
+ | |||
+ | Writing code that handles interrupts that come from internal peripherals, | ||
+ | |||
+ | === Delay === | ||
+ | The simplest solution to make functions work for a particular time is to use the '' | ||
+ | '' | ||
+ | |||
+ | The blinking LED code is a simple demonstration of delay functionality: | ||
+ | <code c> | ||
+ | digitalWrite(LED_BUILTIN, | ||
+ | delay(1000); | ||
+ | digitalWrite(LED_BUILTIN, | ||
+ | delay(1000); | ||
+ | </ | ||
+ | Using '' | ||
+ | <figure timers1> | ||
+ | {{: | ||
+ | < | ||
+ | </ | ||
+ | |||
+ | The alternative to using delay is to switch to the non-blocking method, based on timing with the use of '' | ||
+ | |||
+ | === Millis === | ||
+ | '' | ||
+ | <figure timers2> | ||
+ | {{: | ||
+ | < | ||
+ | </ | ||
+ | |||
+ | |||
+ | Here is an example code of blinking LED using '' | ||
+ | |||
+ | <code c> | ||
+ | //Unsigned long should be used to store time values as the millis() returns a 32-bit unsigned number | ||
+ | //Store value of current millis reading | ||
+ | unsigned long currentTime = 0; | ||
+ | //Store value of time when last time the LED state was switched | ||
+ | unsigned long previousTime = 0; | ||
+ | |||
+ | bool ledState = LOW; //Variable for setting LED state | ||
+ | |||
+ | const int stateChangeTime = 1000; //Time at which switch LED states | ||
+ | |||
+ | void setup() { | ||
+ | pinMode (LED_BUILTIN, | ||
+ | } | ||
+ | |||
+ | void loop() { | ||
+ | currentTime = millis(); //Read and store current time | ||
+ | |||
+ | //Calculate passed time since the last state change | ||
+ | //If more time has passed than stateChangeTime, | ||
+ | if (currentTime - previousTime >= stateChangeTime) { | ||
+ | | ||
+ | previousTime = currentTime; | ||
+ | ledState = !ledState; //Change LED state to oposite | ||
+ | digitalWrite(LED_BUILTIN, | ||
+ | } | ||
+ | } | ||
+ | </ | ||
+ | |||
+ | === Sleep Modes === | ||
+ | Some IoT-dedicated microcontrollers have special features such as sleep modes that hold program execution for a predefined time or unless an external trigger occurs. This can be used for periodic, time-based activities. Its side effect is energy efficiency. The model of this behaviour and its features are very vendor-specific and vary much: i.e. Espressif MCUs have the only option to restart the code. At the same time, STM32 can hold execution and then continue. Because of the variety of models, modes and features, we do not present here any specific solution but rather a general idea. | ||
+ | |||
+ | / | ||
+ | | ||
+ | / | ||
+ | | ||
+ | ==== Interrupts ==== | ||
+ | |||
+ | // | ||
+ | |||
+ | ISR should be as short as possible; good practice is avoiding delays and long code sequences. Suppose there is a need to trigger the execution of a long part of the code with an incoming interrupt signal. In that case, the good practice is to define the synchronization variable, modify this variable in the ISR with a single instruction, | ||
+ | |||
+ | Interrupts are used to detect important real-time events which occur during normal code execution of the code. ISR is executed only when there is a need to do it. | ||
+ | |||
+ | === Polling vs. interrupts === | ||
+ | |||
+ | Interrupts can help in efficient data transmission. Using interrupts and checking if some situation occurred periodically is unnecessary. Such continuous checking is named polling. For example, a serial port interrupt is executed only when new data comes without polling the incoming buffer in a loop. This approach saves the processor time and, in many situations, creates code that is more energy efficient. | ||
+ | |||
+ | === Interrupt handling example === | ||
+ | |||
+ | Because interrupts need support from the hardware layer of the microcontroller, | ||
+ | |||
+ | Very often, interrupts are used together with hardware timers to generate stable frequency signals. It ensures accurate timing independent of the main loop content and delays. Because internal peripherals are very different for different microcontrollers in this chapter, the example for the external interrupt is shown. | ||
+ | |||
+ | The function '' | ||
+ | - '' | ||
+ | - '' | ||
+ | - '' | ||
+ | * '' | ||
+ | * '' | ||
+ | * '' | ||
+ | * '' | ||
+ | * '' | ||
+ | |||
+ | The example program that uses external interrupt: | ||
+ | |||
+ | <code c> | ||
+ | volatile bool button_toggle = 0; //A variable to pass the information from ISR to the main program | ||
+ | |||
+ | void setup() { | ||
+ | //Define LED pin | ||
+ | pinMode(13, | ||
+ | //Define button pin | ||
+ | pinMode(2, | ||
+ | //Attach interrupt to button pin | ||
+ | attachInterrupt(digitalPinToInterrupt(2), | ||
+ | } | ||
+ | |||
+ | void ButtonIRS() { //IRS function | ||
+ | button_toggle =!button_toggle; | ||
+ | } | ||
+ | |||
+ | void loop() { | ||
+ | digitalWrite (13, | ||
+ | } | ||
+ | </ | ||
+ | |||
+ | In this example, the code needed to handle the interrupt signal is just one instruction. Still, it shows how to use the synchronization variable to pass information from ISR to the main program keeping the ISR very short. | ||
+ | |||
+ | |||
+ | |||
+ | |||
+ | |||
+ | ==== Programming patterns ==== | ||
+ | This chapter presents some programming templates and fragments of the code that are common in embedded systems. Some of those patterns, such as i.e. non-blocking algorithms, which do not use '' | ||
+ | [[en: | ||
+ | |||
+ | === Tracing vs Debugging - Serial Ports === | ||
+ | Almost any MCU has a hardware debugging capability. This technique is complex and usually requires an external debugger such as JTAG. Setting up hardware and software for simple projects may not be worth a penny; thus, the most frequent case is tracing over debugging. Tracing uses a technique where the Developer explicitly sends some data to the external device (usually a terminal, over a serial port, and eventually a display) that visualises it. The Developer then knows the variables' | ||
+ | Note to use a '' | ||
+ | <code c> | ||
+ | void setup(){ | ||
+ | delay(100); | ||
+ | Serial.begin(115200); | ||
+ | Serial.println(); | ||
+ | ... | ||
+ | } | ||
+ | </ | ||
+ | |||
+ | |||
+ | <note tip>A rule of thumb is that after programming and during a boot, every MCU drops some garbage to the serial buffer. That is visualised as several random characters in the terminal. To easily distinguish the tracing from the garbage, it is advised to put some '' | ||
+ | |||
+ | The '' | ||
+ | * '' | ||
+ | * '' | ||
+ | |||
+ | === Interfacing with the Device - Serial Port === | ||
+ | The serial port and a class '' | ||
+ | <note important> | ||
+ | Data in the serial port are sent as bytes; thus, it is up to the developer to handle the correct data conversion. Reading a single byte of the data is done using '' | ||
+ | |||
+ | === Hardware buttons === | ||
+ | Hardware buttons tend to vibrate when switching. This physical effect causes bouncing of the state forth and back, generating, in fact, a number of pulses instead of a single edge during switching. Getting rid of this is called debouncing. In most cases, switches (buttons) short to 0 (GND) and use pull-up resistors, as in the figure {{ref> | ||
+ | <figure pullupsample> | ||
+ | {{ : | ||
+ | < | ||
+ | </ | ||
+ | The switch, when open, results in VCC through R1 driving the GPIO2 (referenced as HIGH), and when short, 0 is connected to it, so it becomes LOW: | ||
+ | * button short -> GPIO2=LOW | ||
+ | * button released -> GPIO2=HIGH | ||
+ | Some MCUs offer internal pull-ups and pull-downs, configurable from the software level. | ||
+ | The transition state between HIGH and LOW causes bouncing. | ||
+ | |||
+ | A dummy debouncing mechanism only checks periodically for a press/ | ||
+ | <code c> | ||
+ | #define BUTTON_GPIO 2 | ||
+ | |||
+ | bool bButtonPressed=false; | ||
+ | |||
+ | void setup() { | ||
+ | Serial.begin(9600); | ||
+ | pinMode(BUTTON_GPIO, | ||
+ | } | ||
+ | |||
+ | void loop() { | ||
+ | if (digitalRead(BUTTON_GPIO)==LOW && !bButtonPressed) | ||
+ | { | ||
+ | Serial.println(" | ||
+ | delay(200); | ||
+ | bButtonPressed=true; | ||
+ | } | ||
+ | if (bButtonPressed && digitalRead(BUTTON_GPIO)==HIGH) | ||
+ | { | ||
+ | Serial.println(" | ||
+ | bButtonPressed=false; | ||
+ | delay(200); | ||
+ | } | ||
+ | } | ||
+ | </ | ||
+ | A more advanced technique for complex handling of the buttons is presented below in the context of the State Machines. | ||
+ | |||
+ | == Finite State Machine == | ||
+ | A Finite State Machine (FSM) idea represents states and flow conditions between the states that reflect how the software is built for the selected system or its component. An example of button handling with the use of the FSM is present here. The FSM reflects the physical state of the device, sensor or system on the software level, becoming a digital twin of a real device. | ||
+ | |||
+ | For the simple case (without detecting double-click or long press), 3 different button states can be distinguished: | ||
+ | <code c> | ||
+ | typedef enum { | ||
+ | RELEASED = 0, | ||
+ | DEBOUNCING, | ||
+ | PRESSED | ||
+ | } tButtonState; | ||
+ | </ | ||
+ | A flow between the states can be then described in the following diagram (figure {{ref> | ||
+ | <figure statemachine> | ||
+ | {{ : | ||
+ | < | ||
+ | </ | ||
+ | * In the '' | ||
+ | * In the '' | ||
+ | * In the '' | ||
+ | The state machine is implemented as a simple class and has 2 additional fields that store handlers for functions that are called when the state machine enters '' | ||
+ | <code c> | ||
+ | class PullUpButtonHandler{ | ||
+ | private: | ||
+ | tButtonState buttonState=RELEASED; | ||
+ | uint8_t ButtonPin; | ||
+ | unsigned long tDebounceTime; | ||
+ | unsigned long DTmr; | ||
+ | void(*ButtonPressed)(void); | ||
+ | void(*ButtonReleased)(void); | ||
+ | void btReleasedAction() { // | ||
+ | if(digitalRead(ButtonPin)==LOW) { | ||
+ | buttonState = DEBOUNCING; | ||
+ | DTmr = millis(); | ||
+ | } | ||
+ | } | ||
+ | void btDebouncingAction() { // | ||
+ | if(millis()-DTmr > tDebounceTime) | ||
+ | if(digitalRead(ButtonPin)==LOW) { | ||
+ | buttonState = PRESSED; | ||
+ | if(ButtonPressed!=NULL) ButtonPressed(); | ||
+ | } | ||
+ | else | ||
+ | buttonState=RELEASED; | ||
+ | } | ||
+ | void btPressedAction() { //Action to be done when current state is PRESSED | ||
+ | if(digitalRead(ButtonPin)==HIGH) { | ||
+ | buttonState=RELEASED; | ||
+ | if(ButtonReleased!=NULL) ButtonReleased(); | ||
+ | } | ||
+ | } | ||
+ | public: | ||
+ | PullUpButtonHandler(uint8_t pButtonPin, unsigned long pDebounceTime) { // | ||
+ | ButtonPin = pButtonPin; | ||
+ | tDebounceTime = pDebounceTime; | ||
+ | } | ||
+ | void fRegisterBtPressCalback(void (*Callback)()) { //Function registering a On PRESSED callback | ||
+ | ButtonPressed = Callback; | ||
+ | } | ||
+ | void fRegisterBtReleaseCalback(void (*Callback)()) { //Function registering a On RELEASED callback | ||
+ | ButtonReleased = Callback; | ||
+ | } | ||
+ | void fButtonAction() | ||
+ | { // | ||
+ | switch(buttonState) { | ||
+ | case RELEASED: btReleasedAction(); | ||
+ | break; | ||
+ | case DEBOUNCING: btDebouncingAction(); | ||
+ | break; | ||
+ | case PRESSED: btPressedAction(); | ||
+ | break; | ||
+ | default: | ||
+ | break; | ||
+ | } | ||
+ | } | ||
+ | }; | ||
+ | </ | ||
+ | Sample use looks as follows: | ||
+ | <code c> | ||
+ | #define BUTTON_GPIO 2 | ||
+ | |||
+ | PullUpButtonHandler bh = PullUpButtonHandler(BUTTON_GPIO, | ||
+ | void onButtonPressed() { | ||
+ | Serial.println(" | ||
+ | } | ||
+ | void onButtonReleased() { | ||
+ | Serial.println(" | ||
+ | } | ||
+ | void setup() { | ||
+ | Serial.begin(9600); | ||
+ | pinMode(BUTTON_GPIO, | ||
+ | bh.fRegisterBtPressCalback(onButtonPressed); | ||
+ | bh.fRegisterBtReleaseCalback(onButtonReleased); | ||
+ | } | ||
+ | |||
+ | void loop() { | ||
+ | bh.fButtonAction(); | ||
+ | } | ||
+ | </ | ||
+ | <note important> | ||
+ | The great feature of this FSM is that it can be easily extended with new functions, such as i.e. detection of the double click or long button press. | ||
+ | |||
+ | ==== Hardware-specific extensions in programming ==== | ||
+ | Some generic programming techniques and patterns mentioned above require adaptation for different hardware platforms. It may occur whenever hardware-related aspects are in charge, i.e., accessing GPIOs, ADC conversion, timers, interrupts, multitasking (task scheduling and management), | ||
+ | It is common for hardware vendors to provide rich examples, either in the form of documentation and downloadable samples (i.e. STM) or via Github (Espressif), | ||
+ | |||
+ | === Analog input === | ||
+ | Some MCUs use specific setups. Analogue input may work out of the box. Still, low-level control usually brings better results and higher flexibility (i.e. instead of changing the input voltage to reflect the whole measurement range, you can regulate internal amplification and sensitivity. | ||
+ | |||
+ | == A special note on analogue inputs in ESP32 == | ||
+ | Please note implementation varies even between the ESP32 chips family, and not all chips provide all of the functions, so it is essential to refer to the technical documentation ((https:// | ||
+ | |||
+ | ESP32 has 15 channels exposed (18 total) of the up to 12-bit resolution ADCs. Reading the raw data (12-bit resolution is the default, 8 samples per measure as default) using the '' | ||
+ | Technically, | ||
+ | Just execute '' | ||
+ | Several useful functions are here (not limited to): | ||
+ | * '' | ||
+ | * '' | ||
+ | * '' | ||
+ | * '' | ||
+ | * '' | ||
+ | * '' | ||
+ | * '' | ||
+ | * '' | ||
+ | |||
+ | <note important> | ||
+ | |||
+ | === Analog output === | ||
+ | PWM frequently controls analogue-style, | ||
+ | PWM uses pulses to change the adequate power delivered to the actuator. | ||
+ | It applies to motors, LEDs, bulbs, heaters and indirectly to the servos (but that works another way). | ||
+ | |||
+ | == A special note on ESP32 MCUs == | ||
+ | The classical '' | ||
+ | ESP32 has up to sixteen (0 to 15) PWM channels (controllers) that can be freely bound to any of the regular GPIOs.\\ The exact number of PWM channels depends on the family member of the ESP chips, i.e. ESP32-S2 and S3 series have only 8 independent PWM channels while ESP32-C3 has only 6. In the Arduino software framework for ESP32, it is referred to as '' | ||
+ | |||
+ | To use PWM in ESP32, one must perform the following steps: | ||
+ | * configure GPIO pin as '' | ||
+ | * initiate PWM controller by fixing PWM frequency and resolution, | ||
+ | * bind the controller to the GPIO pin, | ||
+ | * write to the controller (not to the PIN!) providing a duty cycle related to the resolution selected above - every call persistently sets the PWM duty cycle until the next call to the function setting duty cycle. | ||
+ | |||
+ | More information and detailed references can be found in the technical documentation for the ESP32 chips family ((https:// | ||
+ | |||
+ | Sample code controlling an LED on GPIO 26 with 5kHz frequency and 8-bit resolution is presented below: | ||
+ | <code c> | ||
+ | #include " | ||
+ | |||
+ | ... | ||
+ | |||
+ | #define RGBLED_R 26 | ||
+ | #define PWM1_Ch | ||
+ | #define PWM_Res | ||
+ | #define PWM_Freq | ||
+ | |||
+ | ... | ||
+ | |||
+ | ledcSetup(PWM1_Ch, | ||
+ | ledcAttachPin(RGBLED_R, | ||
+ | ledcWrite(PWM1_Ch, | ||
+ | ... | ||
+ | </ | ||
+ | |||
+ | <note tip>You can bind one PWM channel to many GPIOs to control them synchronously.</ | ||
+ | |||
+ | This technique can be easily adapted to control, e.g. standard and digital servos. PWM signal specification to control servos is presented in the chapter [[en: | ||
+ | |||
+ | === Interrupts === | ||
+ | Arduino boards used to have a limited set of GPIOs to trigger interrupts. In other MCUs, it is a rule of thumb that almost all GPIOs (but those used, i.e. for external SPI flash) can trigger an interrupt; thus, there is much higher flexibility in, i.e., the use of user interface devices such as buttons. | ||
+ | |||
+ | == A special note on ESP8266 and ESP32 == | ||
+ | Suppose the interrupt routine (function handler) uses any variables or access flash memory. In that case, it is necessary to use some tagging of the ISR function because of the specific, low-level memory management. A use of '' | ||
+ | <code c> | ||
+ | void IRAM_ATTR ButtonIRS() { //IRS function | ||
+ | button_toggle =!button_toggle; | ||
+ | } | ||
+ | </ | ||
+ | |||
+ | <note important> | ||
+ | |||
+ | <note warning> | ||
+ | |||
+ | === Timers === | ||
+ | The number of hardware timers, their features, and specific configuration is per MCU. Even single MCU families have different numbers of timers, i.e., in the case of the STM32 chips, the ESP32, and many others. Those differences, | ||
+ | |||
+ | == A special note on ESP32 MCUs == | ||
+ | The number of hardware timers varies between family members. Most ESP32s have 4, but ESP32-C3 has only two ((https:// | ||
+ | Special techniques using the critical section, muxes and semaphores are needed when more than one routine writes to the shared variable between processes (usually main code and an interrupt handler). However, It is unnecessary in the scenario where the interrupt handler writes to the variable and some other code (i.e. in the '' | ||
+ | In this example, the base clock for the timer in the ESP32 chip is 80MHz, and the timer ('' | ||
+ | '' | ||
+ | <code c> | ||
+ | #include " | ||
+ | |||
+ | #define LED_GPIO 0 //RED LED on GPIO 0 - vendor-specific | ||
+ | #define PRESCALLER 80 // | ||
+ | #define COUNTER 2000000 //2 million us = 2s | ||
+ | |||
+ | volatile bool LEDOn = false; | ||
+ | hw_timer_t *tHBT = NULL; //Heart Beat Timer | ||
+ | |||
+ | void IRAM_ATTR onHBT(){ | ||
+ | LEDOn = !LEDOn; | ||
+ | } | ||
+ | |||
+ | void setup() { | ||
+ | Serial.begin(9600); | ||
+ | pinMode(LED_GPIO, | ||
+ | |||
+ | tHBT = timerBegin(0, | ||
+ | // Most ESP32s (but ESP32-C3) have 4 timers (0-3), and ESP32-C3 has only two (0-1). | ||
+ | if (tHBT==NULL) //Check timer is created OK, NULL otherwise | ||
+ | { | ||
+ | Serial.println(" | ||
+ | delay(1000); | ||
+ | ESP.restart(); | ||
+ | } | ||
+ | timerAttachInterrupt(tHBT, | ||
+ | timerAlarmWrite(tHBT, | ||
+ | timerAlarmEnable(tHBT); | ||
+ | | ||
+ | } | ||
+ | //Loop function only reads LEDOn value and updates GPIO accordingly | ||
+ | void loop() { | ||
+ | digitalWrite(LED_GPIO, | ||
+ | } | ||
+ | </ | ||
+ | Timers can also be used to implement a Watchdog. Regarding the example above, it is usually a " | ||
+ | ===== Programming with the use of scripts ===== | ||
+ | Several programming models for IoT script programming are available. Depending on the hardware model used (SoC or OS-based MCU), it may involve single script execution (e.g. Raspberry Pi Pico RP2040, Edge-class IoT) or multithreaded, | ||
+ | |||
+ | Among others, the most common scripting languages for fog class devices are : | ||
+ | * Bash scripting (OS command scripting) usually does not provide support for the GPIO, intended to automate OS tasks; | ||
+ | * Python scripting, cross-platform for both Edge-class devices (Micrpython) and Fog-class (regular Python, usually run on Linux); | ||
+ | * C#, limited to the Windows IoT for Raspberry Pi; | ||
+ | |||
+ | ==== Bash scripting ==== | ||
+ | As Bash scripting is well covered by many manuals for Linux, in the following chapters, we focus on two others: Python and C#. Moreover, accessing the GPIO in the case of the bash requires installing external tools; thus, it does not apply to IoT programming straightforwardly but rather as a supplementary tool to automate tasks other than core programming. | ||
+ | ==== Python ==== | ||
+ | Python programming for IoT devices is dual: | ||
+ | * [[en: | ||
+ | * [[en: | ||
+ | ==== C# .NET ==== | ||
+ | [[en: | ||
+ | |||
+ | <todo @pczekalski> | ||
+ | <todo @pczekalski> | ||
+ | ~~NOTOC~~ | ||
+ | ==== ==== | ||
+ | <box # | ||
+ | <box # | ||
+ | ==== Introduction to the Python programming for IoT ==== | ||
+ | <box # | ||
+ | <box # | ||
+ | |||
+ | A program in Python is stored in text files on the device' | ||
+ | In the context of IoT programming, | ||
+ | Python is simple and efficient in programming the not-so-complex IoT algorithms but does not offer the level of control needed in real-time applications. It can be easily used for prototyping, | ||
+ | |||
+ | < | ||
+ | |||
+ | Nowadays, Python interpreter usually comes with OS (Linux) preinstalled. | ||
+ | The sample installation procedure for Raspbian OS is presented in the manual maintained by the Raspberry Pi manufacturer ((https:// | ||
+ | In the case of the popular Raspbian or Ubuntu for Raspberry Pi, there are usually 2 versions of Pythons preinstalled: | ||
+ | Python version can be started from the terminal simply by calling: | ||
+ | <code bash> | ||
+ | ~$ python --version | ||
+ | Python 3.8.10 | ||
+ | </ | ||
+ | In the case one needs to use a specific version, you can start the interpreter explicitly referring to Python 2 or Python 3: | ||
+ | <code bash> | ||
+ | ~$ python2 | ||
+ | Python 2.7.18 (default, Jul 29 2022, 09: | ||
+ | [GCC 9.4.0] on linux2 | ||
+ | Type " | ||
+ | >>> | ||
+ | |||
+ | ~$ python3 | ||
+ | Python 3.8.10 (default, May 26 2023, 14: | ||
+ | [GCC 9.4.0] on linux | ||
+ | Type " | ||
+ | >>> | ||
+ | |||
+ | </ | ||
+ | |||
+ | Python can be executed via a desktop graphical interface (in the graphical terminal), in a text-based Linux installation via terminal, or remotely via ssh. As it is possible to write applications with visual GUI, starting them in a non-graphical installation of the Linux OS will throw an error. To execute a Python script (program), one needs to execute the following: | ||
+ | <code bash> | ||
+ | ~$ python mypythoniotapp.py | ||
+ | </ | ||
+ | |||
+ | Linux, Windows and Mac systems used to bind a '' | ||
+ | <code bash> | ||
+ | ~$ ./ | ||
+ | </ | ||
+ | |||
+ | <note tip> | ||
+ | |||
+ | In the following chapters, we present Python coding elements that are specific to the microcontrollers. A full Python course is beyond the scope of this publication, | ||
+ | |||
+ | === IDEs for Python === | ||
+ | A dozen of IDEs can be used to program in Python. The most common are: | ||
+ | * IDLE Editor, formerly delivered with Raspbian OS in the bundle, requires GUI. It is currently obsolete but still popular among hobbyists. | ||
+ | * Thonny Python IDE, which comes with Raspbian OS, recently took over IDLE. | ||
+ | * Visual Studio Code with plugins for Python, common with Arduino framework and easily integrates remote Python development - it provides two development scenarios: local on the IoT device (Raspberry Pi, requires GUI) and remote from the PC to the IoT device, that works with headless Raspberry Pi OSes installations. | ||
+ | * PyCharm Community Edition requires additional installation ((https:// | ||
+ | * Simple code can be authored in the terminal using any text editor (i.e. Nano), as Python source files do not require compilation and are plain text ones. This is not very convenient, but it can help if no dedicated IDE and GUI are available, e.g., for rapid work remotely. | ||
+ | |||
+ | The following subchapters present some IoT and embedded systems-specific Python programming and a very basic introduction: | ||
+ | * [[en: | ||
+ | * [[en: | ||
+ | * [[en: | ||
+ | * [[en: | ||
+ | * [[en: | ||
+ | * [[en: | ||
+ | |||
+ | === Additional Resources for Python programming for beginners === | ||
+ | For in-depth Python courses and more, follow the links: | ||
+ | - The Python syntax and semantics: [[https:// | ||
+ | - The Python Package Index (PyPi): [[https:// | ||
+ | - The Python Standard Library: | ||
+ | - Free online Python course: [[https:// | ||
+ | |||
+ | <todo @pczekalski # | ||
+ | |||
+ | |||
+ | |||
+ | <todo @pczekalski> | ||
+ | === === | ||
+ | <box # | ||
+ | <box # | ||
+ | ===Python Data Types and Variables=== | ||
+ | <box # | ||
+ | <box # | ||
+ | |||
+ | Python aims to be consistent and straightforward in the design of its syntax. The best advantage of this language is that it can dynamically set the variable types depending on values types which are set for variables. | ||
+ | |||
+ | ==Base Types== | ||
+ | Python has a wide range of data types, like many simple programming languages: | ||
+ | * number, | ||
+ | * string, | ||
+ | * list, | ||
+ | * tuple | ||
+ | * dictionary. | ||
+ | |||
+ | ==Numbers== | ||
+ | Standard Python methods are used to create the numbers: | ||
+ | <code Python> | ||
+ | var = 1234 # | ||
+ | var = ' | ||
+ | </ | ||
+ | |||
+ | Python can automatically convert types of the number from one type to another. Type can be also defined explicitly. | ||
+ | <code Python> | ||
+ | int a = 10 | ||
+ | long a = 123L | ||
+ | float a = 12.34 | ||
+ | complex a = 3.23J | ||
+ | < | ||
+ | |||
+ | ==String== | ||
+ | To define Strings use eclosing characters in quotes. | ||
+ | Python uses single quotes ', double " and triple """ | ||
+ | <code Python> | ||
+ | Name = " | ||
+ | lastName = " | ||
+ | message = """ | ||
+ | </ | ||
+ | |||
+ | ==List== | ||
+ | List contains a series of values. To declare list variables uses brackets []. | ||
+ | <code Python> | ||
+ | A = [] #Blank list variable | ||
+ | B = [1, 2, 3] #List with 3 numbers | ||
+ | C = [1, ' | ||
+ | </ | ||
+ | List are zero-based indexed. Data can be assigned to a specific element of the list using an index into the list. | ||
+ | <code Python> | ||
+ | mylist[0] = ' | ||
+ | mylist[1] = ' | ||
+ | |||
+ | print mylist[1] | ||
+ | </ | ||
+ | List aren't limited to a single dimension. | ||
+ | <code Python> | ||
+ | myTable = [[],[]] | ||
+ | </ | ||
+ | In two-dimensional array the first number is always the rows number, when the second is the columns number. | ||
+ | |||
+ | ==Tuple== | ||
+ | Python Tuples are defined as a group of values like a list and can be processed in similar ways. When assigned Tuples got the fixed size. In Python, the fixed size is immutable. The lists are dynamic and mutable. To define Tuples, parenthesis () must be used. | ||
+ | <code Python> | ||
+ | TestSet = (' | ||
+ | </ | ||
+ | |||
+ | == Dictionary== | ||
+ | To define the Dictionaries in the Python the lists of key--value pairs are used. This datatype is used to hold related information that can be associated through Keys. The Dictionary is used to extract a value based on the key name. Lists use the index numbers to access its members when dictionaries use a key. Dictionaries generally are used to sort, iterate and compare data. | ||
+ | |||
+ | To define the Dictionaries the braces ({}) are used with pairs separated by a comma (,) and the key values associated with a colon (:). Dictionaries Keys must be unique. | ||
+ | <code Python> | ||
+ | box_nbr = {' | ||
+ | box_nbr[' | ||
+ | print (box nbr[' | ||
+ | box_nbr[' | ||
+ | print (box_nbr.keys()) | ||
+ | print (' | ||
+ | #This returns true | ||
+ | </ | ||
+ | |||
+ | |||
+ | All variables in Python hold references to objects, and are passed to functions. Function can't change the value of variable references in its body. The object' | ||
+ | < | ||
+ | >>> | ||
+ | >>> | ||
+ | al.append(' | ||
+ | print al | ||
+ | |||
+ | >>> | ||
+ | [' | ||
+ | >>> | ||
+ | [' | ||
+ | </ | ||
+ | === === | ||
+ | <box # | ||
+ | <box # | ||
+ | ===Python Program Control Structures=== | ||
+ | <box # | ||
+ | <box # | ||
+ | |||
+ | ==if Statements== | ||
+ | If an expression returns //TRUE// statements are carried out. Otherwise they aren' | ||
+ | <code Python> | ||
+ | if expression: | ||
+ | statements | ||
+ | </ | ||
+ | |||
+ | Sample: | ||
+ | <code Python> | ||
+ | no = 11 | ||
+ | if no >10: | ||
+ | print (" | ||
+ | if no <=30 | ||
+ | | ||
+ | </ | ||
+ | Output: | ||
+ | < | ||
+ | >>> | ||
+ | Greater than 10 | ||
+ | Between 10 and 30 | ||
+ | >>> | ||
+ | </ | ||
+ | |||
+ | ==else Statements== | ||
+ | An //else// statement follows an //if// statement and contains code that is called when the if statement is //FALSE//. | ||
+ | <code Python> | ||
+ | x = 2 | ||
+ | if x == 6 | ||
+ | printf (" | ||
+ | else: | ||
+ | printf (" | ||
+ | </ | ||
+ | |||
+ | ==elif Statements== | ||
+ | The //elif// (shortcut of //else if//) statement is used when changing //if// and //else// statements. A series of // | ||
+ | <code Python> | ||
+ | num = 12 | ||
+ | if num == 5: | ||
+ | printf (" | ||
+ | elif num == 4: | ||
+ | printf (" | ||
+ | elif num == 3: | ||
+ | printf (" | ||
+ | else: | ||
+ | printf (" | ||
+ | </ | ||
+ | Output: | ||
+ | < | ||
+ | >>> | ||
+ | | ||
+ | >>> | ||
+ | </ | ||
+ | |||
+ | ==Boolean Logic== | ||
+ | Python uses logic operators like //AND//, //OR// and //NOT//. | ||
+ | |||
+ | The //AND// operator uses two arguments, and evaluates to //TRUE// if, and only if, both of the arguments are //TRUE//. Otherwise, it evaluates to //FALSE//. | ||
+ | <code Python> | ||
+ | >>> | ||
+ | True | ||
+ | >>> | ||
+ | False | ||
+ | >>> | ||
+ | False | ||
+ | >>> | ||
+ | False | ||
+ | >>> | ||
+ | </ | ||
+ | |||
+ | Boolean operator **or** uses two arguments, and evaluates as //TRUE// if either (or both) of its arguments are //TRUE//, and //FALSE// if both arguments are //FALSE//. | ||
+ | |||
+ | The result of //NOT TRUE// is //FALSE//, and // NOT FALSE// goes to //TRUE//. | ||
+ | <code Python> | ||
+ | >>> | ||
+ | False | ||
+ | >>> | ||
+ | True | ||
+ | >>> | ||
+ | </ | ||
+ | |||
+ | == Operator Precedence== | ||
+ | Operator Precedence uses mathematical idea of operation order, e.g. multiplication begin performed before addition. | ||
+ | |||
+ | <code Python> | ||
+ | >>> | ||
+ | True | ||
+ | >>> | ||
+ | False | ||
+ | >>> | ||
+ | >>> | ||
+ | >>> | ||
+ | </ | ||
+ | |||
+ | |||
+ | |||
+ | === === | ||
+ | <box # | ||
+ | <box # | ||
+ | ===Python Looping=== | ||
+ | <box # | ||
+ | <box # | ||
+ | |||
+ | == while Loop== | ||
+ | An //if// statement is run once if its condition evaluates to //TRUE//, and never if it evaluates to //FALSE//. | ||
+ | |||
+ | A //while// statement is similar, except that it can be run more than once. The statements inside it are repeatedly executed, as long as the condition holds. Once it evaluates to //FALSE//, the next section of code is executed. | ||
+ | <code Python> | ||
+ | i = 1 | ||
+ | while i<=4: | ||
+ | print (i) | ||
+ | i+=1 | ||
+ | print (' | ||
+ | </ | ||
+ | |||
+ | Output: | ||
+ | < | ||
+ | >>> | ||
+ | 1 | ||
+ | 2 | ||
+ | 3 | ||
+ | 4 | ||
+ | End | ||
+ | >>> | ||
+ | </ | ||
+ | |||
+ | The **infinite loop** is a particular kind of the //while// loop, it never stops running. Its condition always remains //TRUE//. | ||
+ | |||
+ | <code Python> | ||
+ | while 1 == 1: | ||
+ | print ('in the loop') | ||
+ | </ | ||
+ | |||
+ | To end the //while// loop prematurely, | ||
+ | When encountered inside a loop, the break statement causes the loop to finish immediately. | ||
+ | <code Python> | ||
+ | i = 0 | ||
+ | while 1==1: | ||
+ | print (i) | ||
+ | i += 1 | ||
+ | if i >=3: | ||
+ | print(' | ||
+ | break; | ||
+ | print (' | ||
+ | </ | ||
+ | |||
+ | Output: | ||
+ | < | ||
+ | >>> | ||
+ | 0 | ||
+ | 1 | ||
+ | 2 | ||
+ | 3 | ||
+ | breaking | ||
+ | finished | ||
+ | >>> | ||
+ | </ | ||
+ | |||
+ | Another statement that can be used within loops is **continue**. | ||
+ | |||
+ | Unlike break, continue jumps back to the top of the loop, rather than stopping it. | ||
+ | <code Python> | ||
+ | i = 0 | ||
+ | while True: | ||
+ | i+=1 | ||
+ | if i == 2: | ||
+ | printf (' | ||
+ | continue | ||
+ | if i == 5: | ||
+ | print (' | ||
+ | break | ||
+ | print (i) | ||
+ | print (' | ||
+ | </ | ||
+ | |||
+ | Output: | ||
+ | < | ||
+ | >>> | ||
+ | 1 | ||
+ | skipping 2 | ||
+ | 3 | ||
+ | 4 | ||
+ | breaking | ||
+ | finished | ||
+ | >>> | ||
+ | </ | ||
+ | |||
+ | == for Loop== | ||
+ | |||
+ | <code Python> | ||
+ | n = 9 | ||
+ | for i in range (1,5): | ||
+ | ml = n * i | ||
+ | print ("{} * {} = {}" | ||
+ | </ | ||
+ | |||
+ | Output: | ||
+ | < | ||
+ | >>> | ||
+ | 9 * 1 = 9 | ||
+ | 9 * 2 = 18 | ||
+ | 9 * 3 = 27 | ||
+ | 9 * 4 = 36 | ||
+ | >>> | ||
+ | </ | ||
+ | |||
+ | === === | ||
+ | <box # | ||
+ | <box # | ||
+ | === Python Sub-Programs === | ||
+ | <box # | ||
+ | <box # | ||
+ | |||
+ | ==Subprograms== | ||
+ | One of the most important in mathematics concept is to use functions. Functions in computer languages implement mathematical functions. The executing function produces one or more results, which are dependent by the parameters passed to it. | ||
+ | |||
+ | In general, a function is a structuring element in the programming language which groups a set of statements so they can be called more than once in a program. Programming without functions will need to reuse code by copying it and changing its different context. Using functions enhances the comprehensibility and quality of the program. It also lowers the memory usage, development cost and maintenance of the software. | ||
+ | |||
+ | Different naming is used for functions in programming languages, e.g. as subroutines, | ||
+ | |||
+ | Python language defines function by a //def// statement. The function syntax looks: | ||
+ | < | ||
+ | def function-name(Parameter list): | ||
+ | statements, i.e. the function body | ||
+ | </ | ||
+ | Function bodie can contain one or more return statement. It can be situated anywhere in the function body. A return statement ends the function execution and returns the result, i.e. to the caller. If the return statement does not contain expression, the value //None// is returned. | ||
+ | <code Python> | ||
+ | def Fahrenheit(T_in_celsius): | ||
+ | """ | ||
+ | return (T_in_celsius * 9 / 5) + 32 | ||
+ | |||
+ | for t in (22.6, 25.8, 27.3, 29.8): | ||
+ | print(t, ": ", fahrenheit(t)) | ||
+ | </ | ||
+ | Output: | ||
+ | < | ||
+ | >>> | ||
+ | 22.6 : 72.68 | ||
+ | 25.8 : 78.44 | ||
+ | 27.3 : 81.14 | ||
+ | 29.8 : 85.64 | ||
+ | >>> | ||
+ | </ | ||
+ | |||
+ | ==Optional Parameters== | ||
+ | Functions can be called with optional parameters, also named default parameters. If function is called without parameters the default values are used. The following code greets a person. If no person name is defined, it greets everybody: | ||
+ | <code Python> | ||
+ | def Hello(name=" | ||
+ | """ | ||
+ | print(" | ||
+ | |||
+ | Hello(" | ||
+ | Hello() | ||
+ | </ | ||
+ | |||
+ | Output: | ||
+ | < | ||
+ | >>> | ||
+ | Hello George! | ||
+ | Hello everybody! | ||
+ | >>> | ||
+ | </ | ||
+ | |||
+ | ==Docstrings== | ||
+ | The string is usually the first statement in the function body, which can be accessed with function_name.doc. | ||
+ | This is Docstring statement. | ||
+ | <code Python> | ||
+ | def Hello(name=" | ||
+ | """ | ||
+ | print(" | ||
+ | print(" | ||
+ | </ | ||
+ | |||
+ | Output: | ||
+ | < | ||
+ | >>> | ||
+ | The function Hello docstring: | ||
+ | >>> | ||
+ | </ | ||
+ | |||
+ | ==Keyword Parameters== | ||
+ | The alternative way to make function calls is to use keyword parameters. The function definition stay unchanged. | ||
+ | <code Python> | ||
+ | def sumsub(a, b, c=0, d=0): | ||
+ | return a - b + c - d | ||
+ | print(sumsub(12, | ||
+ | print(sumsub(42, | ||
+ | </ | ||
+ | |||
+ | Only keyword parameters are valid, which are not used as positional arguments. If keyword parameters don't exist, the next call to the function will need all four arguments, even if the //c// needs just the default value: | ||
+ | <code Python> | ||
+ | print(sumsub(42, | ||
+ | </ | ||
+ | |||
+ | ==Return Values== | ||
+ | In above examples, the return statement exist in sumsub but not in //Hello// function. The return statement is not mandatory. If explicitly return statement doesn' | ||
+ | <code Python> | ||
+ | def no_return(x, | ||
+ | c = x + y | ||
+ | res = no_return(4, | ||
+ | print(res) | ||
+ | </ | ||
+ | |||
+ | Any result will not be displayed in: | ||
+ | < | ||
+ | >>> | ||
+ | </ | ||
+ | |||
+ | Executing this script, the //None// will be printed. If a function doesn' | ||
+ | <code Python> | ||
+ | def empty_return(x, | ||
+ | c = x + y | ||
+ | return | ||
+ | res = empty_return(4, | ||
+ | print(res) | ||
+ | </ | ||
+ | |||
+ | Otherwise the expression value following return will be returned. In this example 11 will be printed: | ||
+ | <code Python> | ||
+ | def return_sum(x, | ||
+ | c = x + y | ||
+ | return c | ||
+ | res = return_sum(6, | ||
+ | print(res) | ||
+ | </ | ||
+ | |||
+ | Output: | ||
+ | < | ||
+ | >>> | ||
+ | 9 | ||
+ | >>> | ||
+ | </ | ||
+ | |||
+ | ==Multiple Values Returning== | ||
+ | Any function can return only one object. An object can be a numerical value -- integer, float, list or a dictionary. To return i.e. three integer values, we can return a list or a tuple with these three integer values. It means that function can indirectly return multiple values. This following example calculates the Fibonacci boundary for a positive number, returns a 2-tuple. The Largest Fibonacci Number smaller than //x// is the first and the Smallest Fibonacci Number larger than //x// is next. The return value is stored via unpacking into the variables lub and sup: | ||
+ | <code Python> | ||
+ | def fib_intervall(x): | ||
+ | """ | ||
+ | Fibonacci number, higher than x""" | ||
+ | if x < 0: | ||
+ | return -1 | ||
+ | (old, new, lub) = (0,1,0) | ||
+ | while True: | ||
+ | if new < x: | ||
+ | lub = new | ||
+ | (old,new) = (new, | ||
+ | else: | ||
+ | return (lub, new) | ||
+ | | ||
+ | while True: | ||
+ | x = int(input(" | ||
+ | if x <= 0: | ||
+ | break | ||
+ | (lub, sup) = fib_intervall(x) | ||
+ | print(" | ||
+ | print(" | ||
+ | </ | ||
+ | |||
+ | |||
+ | === === | ||
+ | <box # | ||
+ | <box # | ||
+ | === Python for Hardware === | ||
+ | <box # | ||
+ | <box # | ||
+ | |||
+ | == Controlling GPIO == | ||
+ | |||
+ | The following code presents a sample Python application that flashes an LED connected to Raspberry Pi's GPIO pin 5. One must build a circuit (LED + resistor of a proper value) and connect it to the GPIO before running the code.\\ | ||
+ | This example uses a dedicated GPIO handling library (specific for hardware): '' | ||
+ | |||
+ | <code Python> | ||
+ | #Raspberry Pi Python sample code | ||
+ | |||
+ | import RPi.GPIO as GPIO | ||
+ | import time | ||
+ | |||
+ | #Blinking function | ||
+ | def blink(pin): | ||
+ | GPIO.output(pin, | ||
+ | time.sleep(1) | ||
+ | GPIO.output(pin, | ||
+ | time.sleep(1) | ||
+ | return | ||
+ | |||
+ | #Use the Raspberry Pi GPIO pin numbers | ||
+ | GPIO.setmode(GPIO.BOARD) | ||
+ | #Set up GPIO output channel | ||
+ | GPIO.setup(5, | ||
+ | #Blink GPIO5 5 times | ||
+ | for i in range(0, | ||
+ | blink(5) | ||
+ | GPIO.cleanup() | ||
+ | </ | ||
+ | |||
+ | ==Interrupts Handling== | ||
+ | Similarly to the GPIO, interrupts are hardware-specific; | ||
+ | Following Python rules for working with signals and their handlers are listed below. | ||
+ | |||
+ | - A particular signal handler, once set, remains installed until it is explicitly reset (Python emulates the BSD style interface), except the SIGCHLD handler, which follows the underlying implementation. | ||
+ | - The critical section signal can't be “blocked” temporarily (all Unix flavours do not support it). | ||
+ | - Python signal handlers are called asynchronously as far as the Python user is concerned; they can only occur between the “atomic” instructions of the Python interpreter. Signals arriving during long calculations implemented in C (such as regular expression matches on large bodies of text) may be delayed for an arbitrary amount of time. | ||
+ | - When a signal arrives during an I/O operation, it is possible that the I/O operation raises an exception after the signal handler returns. It depends on the underlying Unix system’s semantics. | ||
+ | - The C signal handler always returns; it makes little sense to catch synchronous errors like SIGFPE or SIGSEGV. | ||
+ | - Python installs several signal handlers by default: SIGPIPE is ignored, and SIGINT is translated into a KeyboardInterrupt exception. All of them can be overridden. | ||
+ | - Some care must be taken if both signals and threads are used in the same program. When using signals and threads simultaneously, | ||
+ | - Any thread can perform an // | ||
+ | - Use locks instead. | ||
+ | |||
+ | The example program is shown below. It uses the //alarm()// function to limit the time spent waiting to open a file; very useful if the file needs to be transmitted over a serial device that may not be turned on, which would typically cause the // | ||
+ | <code Python> | ||
+ | #Raspberry Pi Python sample code | ||
+ | import RPi.GPIO as GPIO | ||
+ | import time | ||
+ | |||
+ | state = 0 | ||
+ | |||
+ | GPIO.setmode(GPIO.BCM) | ||
+ | GPIO.setup(26, | ||
+ | GPIO.setup(19, | ||
+ | |||
+ | def interrupt_handler(channel): | ||
+ | global state | ||
+ | |||
+ | print(" | ||
+ | |||
+ | if channel == 19: | ||
+ | if state == 1: | ||
+ | state = 0 | ||
+ | print(" | ||
+ | elif channel == 26: | ||
+ | if state == 0: | ||
+ | state = 1 | ||
+ | print(" | ||
+ | |||
+ | GPIO.add_event_detect(26, | ||
+ | callback=interrupt_handler, | ||
+ | bouncetime=200) | ||
+ | GPIO.add_event_detect(19, | ||
+ | callback=interrupt_handler, | ||
+ | bouncetime=200) | ||
+ | while (True): | ||
+ | time.sleep(0) | ||
+ | </ | ||
+ | |||
+ | / | ||
+ | | ||
+ | / | ||
+ | | ||
+ | ====== Embedded communication ====== | ||
+ | |||
+ | IoT systems and related data flows are typically structured into three basic layers {{ref> | ||
+ | ((Internet of Things: Architectures, | ||
+ | ((Internet of Things: Security Vulnerabilities and Challenges; I. Andrea, C. Chrysostomou, | ||
+ | The lowest layer is the Perception (physical, acquisition) Layer, the intermediate is the Network Layer, and the higher is the Application Layer. The function of the Perception layer is to keep in contact with the physical environment. Devices working in this layer are designed as embedded systems with a network module. The modern embedded device includes a microcontroller, | ||
+ | |||
+ | <figure iotstack3> | ||
+ | {{ : | ||
+ | < | ||
+ | </ | ||
+ | |||
+ | <figure iotstack5> | ||
+ | {{ : | ||
+ | < | ||
+ | </ | ||
+ | |||
+ | This chapter describes some popular internal protocols used to communicate between microcontrollers and other electronic elements called “embedded protocols”. | ||
+ | |||
+ | The embedded protocol that can be used in specific implementation depends mainly on the type of peripheral element. The method of connection and data exchange strictly depends on the kind of element. Some parts are analogue sensors that should be connected to an analogue-digital converter; some can be connected to digital pins working as inputs (for sensors) or outputs (for actuators). | ||
+ | |||
+ | ===== Analog ===== | ||
+ | Simple sensors do not implement the conversion and communication logic, and the output is just the analogue signal – voltage level, depending on the value of the measured parameter. It needs to be further converted into a digital representation; | ||
+ | Examples of sensors with analogue output are a photoresistor, | ||
+ | ADC conversion is a process of conversion of the continuous-time signal into a discrete one. It has 2 crucial parameters to consider: | ||
+ | * Sampling rate: usually measured in Hz (kHz, MHz) is a sampling frequency, or in other words, defines a time period between two consecutive reads. A Nyquist-Shannon theorem defines minimum sampling frequency. Oversampling (using higher than Nyquist-Shannon) is common because many ADC converters built into the MCUs tend to be noisy due to the electromagnetic inference of other components, such as e.g. built-in radio. Oversampling brings the capability to average consecutive reads and obtain more reliable and less noisy ADC conversion. | ||
+ | * Sampling resolution: measured in bits, defines the minimum change in the input voltage that the device can measure, i.e. 12-bit resolution brings 4096 values that are mapped to the input range. Obviously, the ideal ADC converter maps the discrete values to the voltage input range in a linear way. Still, in real-life applications, | ||
+ | It is worth noting to mention that each ADC has its useable input range (voltage), and the input and analogue signal should be altered accordingly. In real applications, | ||
+ | |||
+ | ===== Digital ===== | ||
+ | Simple, true/false information can be processed via digital I/O. Most devices use positive logic, where, i.e. +5 V (TTL) or +3.3 V (the most popular, yet other voltage standards exist) presents a logical one, also referenced as //HIGH//. In contrast, 0V presents a logical zero, referenced as //LOW//. In real systems, this bounding is fuzzy. It brings some tolerance, simplifying, | ||
+ | Alternating //HIGH// and //LOW// constitutes a square wave signal, usually used as a clock signal (when symmetrical) or used to control the power delivered to the external devices with means of so-called [[en: | ||
+ | |||
+ | |||
+ | ===== Communication protocols ===== | ||
+ | Elements that need more data to be transferred (e.g. displays) usually use some digital data transmission protocol. It is often a serial protocol, meaning that data is transmitted bit by bit. Serial communication can be done in three modes. | ||
+ | * In simplex mode, only one of the two devices on a link can transmit; the other can only receive. The simplex mode can use the entire capacity of the channel to send data. | ||
+ | * In half-duplex mode, each station can transmit and receive, but not simultaneously. When one device sends, the other can only receive, and vice versa. | ||
+ | * In full-duplex mode, both stations can transmit and receive simultaneously. The link must contain two physically separate transmission paths, one for sending and the other for receiving. | ||
+ | |||
+ | Serial data transmission can be done synchronously or asynchronously. In synchronous data transmission, | ||
+ | Asynchronous data transmission does not need any separate synchronization signal, but the transmitter and receiver must use the exact timings and synchronization information must be included in the information transmitted. Examples of asynchronous interfaces implemented in microcontrollers are 1-Wire and UART (Universal Asynchronous Receiver Transmitter). | ||
+ | |||
+ | * [[en: | ||
+ | * [[en: | ||
+ | * [[en: | ||
+ | * [[en: | ||
+ | |||
+ | |||
+ | ===== PWM ===== | ||
+ | The PWM signal controls the energy delivered to the device, usually a DC motor, LED light, bulb, etc. | ||
+ | To control voltage, instead of using inefficient resistance-based voltage dividers (where the remaining part of the voltage is distracted as heat), PWM is based on approximating the energy delivered to the device with periodical switching on and off (HIGH and LOW). Only two voltages are delivered to the device: low (0V) and HIGH (Vcc, e.g. +5V). One can easily observe how PWM works, e.g. when dimming the LED, if recorded with a high fps camera: the LED light flashes with the PWM signal frequency.\\ | ||
+ | PWM controls, in fact, the ratio between HIGH and LOW signals in one period: the higher the ratio, the more energy is being delivered to the device. It is called a duty cycle. A perfect square wave signal, usually referenced as a clock signal, has a duty cycle of 50% (or 0.5); thus, its energy is half of the energy that can be carried when the signal is HIGH all the time. An LED light with a duty cycle of 100% will be fully bright, and with a duty cycle of 0 will be off. | ||
+ | |||
+ | <note tip>A 50% duty cycle does not necessarily transfer straightforwardly to 50% of brightness or 50% of maximum rpm of the DC motor rotation, as characteristics of the devices regarding the voltage and energy provided to their input may be non-linear.</ | ||
+ | |||
+ | <note important> | ||
+ | |||
+ | PWM signal is then characterised by the following: | ||
+ | * voltage (values when HIGH and LOW), | ||
+ | * frequency, | ||
+ | * duty cycle. | ||
+ | |||
+ | ==== Generating PWM ==== | ||
+ | |||
+ | In microcontrollers, | ||
+ | |||
+ | A frequency of 5kHz is equivalent to 0.2ms period that can be controlled in steps of '' | ||
+ | Sample visualisation of the 5kHz PWM signal (3.3V) is presented in the following figures, with a duty cycle of, respectively: | ||
+ | * 50/ | ||
+ | * 100/ | ||
+ | * 150/ | ||
+ | * 200/ | ||
+ | * 250/ | ||
+ | |||
+ | <figure pwm1> | ||
+ | {{ : | ||
+ | < | ||
+ | </ | ||
+ | |||
+ | <figure pwm2> | ||
+ | {{ : | ||
+ | < | ||
+ | </ | ||
+ | |||
+ | <figure pwm3> | ||
+ | {{ : | ||
+ | < | ||
+ | </ | ||
+ | |||
+ | <figure pwm4> | ||
+ | {{ : | ||
+ | < | ||
+ | </ | ||
+ | |||
+ | <figure pwm5> | ||
+ | {{ : | ||
+ | < | ||
+ | </ | ||
+ | |||
+ | <note important> | ||
+ | |||
+ | A voltage delivered to the device powered with a PWM signal can be calculated as an integral of the PWM signal over time: e.g., a 50% duty cycle of the 5V signal is equivalent to the delivery of the constant 2.5V. | ||
+ | |||
+ | ===== SPI ===== | ||
+ | One of the most popular interfaces to connect different external devices is SPI (Serial Peripheral Interface). It is a synchronous serial interface and protocol that can transmit data with speeds up to 20 Mbps. SPI is used to communicate microcontrollers with one or more peripheral devices over short distances – usually internally in the device. High transmission speed enables SPI to be suitable even for sending animated video data to colourful displays. In SPI connection, there is always one master device, in most cases the microcontroller (μC) that controls the transmission, | ||
+ | <table Ref.Tab.1> | ||
+ | < | ||
+ | ^ <fs xx-small> | ||
+ | | <fs xx-small> | ||
+ | | <fs xx-small> | ||
+ | | <fs xx-small> | ||
+ | | <fs xx-small> | ||
+ | </ | ||
+ | The MISO line is intended to send bits from slave to master, the MOSI wire transmits data from master to slave, and the SCK line sends clock pulses that synchronize data transmission. The master device always generates the clock signal. | ||
+ | Every SPI-compatible device has the SS (Slave Select) input that enables communication in this specific device. Master is responsible for generating this enable signal – separately for every slave in the system. | ||
+ | <figure Ref.Pic.1> | ||
+ | {{ : | ||
+ | < | ||
+ | </ | ||
+ | |||
+ | SPI is used in many electronic elements: | ||
+ | * analogue to digital converters (ADC), | ||
+ | * real-time clocks (RTC), | ||
+ | * EEPROMs, | ||
+ | * LCD, OLED, and e-paper displays, | ||
+ | * communication interfaces (e.g. Ethernet, WiFi), | ||
+ | * and many others. | ||
+ | Due to different hardware implementations, | ||
+ | <table Ref.Tab.2> | ||
+ | < | ||
+ | ^ <fs xx-small> | ||
+ | | <fs xx-small> | ||
+ | | <fs xx-small> | ||
+ | | <fs xx-small> | ||
+ | | <fs xx-small> | ||
+ | </ | ||
+ | |||
+ | It results in different timings of the clock signal concerning the data sent. Clock polarity = 0 means that the idle state of the SCK is 0, so every data bit is synchronised with the pulse of logic 1. Clock polarity = 1 reverses these states. Output edge (rising/ | ||
+ | |||
+ | <figure Ref.Pic.2> | ||
+ | {{ : | ||
+ | < | ||
+ | </ | ||
+ | |||
+ | ===== QSPI ===== | ||
+ | Even if a 20MHz frequency ensures good transmission speed, it can be too slow for some use. Some modern microcontrollers use external flash memory for program storage and execute programs from internal SRAM memory, downloading executable code in chunks as required. This requires a higher data rate to avoid stalls in program execution. A QSPI (Quad-SPI) link was developed to achieve higher transmission speed. It has four bidirectional data lines instead of two unidirectional to increase speed four times. Additionally, | ||
+ | |||
+ | <figure Ref.Pic.3> | ||
+ | {{ : | ||
+ | < | ||
+ | </ | ||
+ | |||
+ | ===== TWI (I2C) ===== | ||
+ | TWI (Two Wire Interface) is one of embedded systems' | ||
+ | * EEPROM memory chips, | ||
+ | * RAM memory chips, | ||
+ | * AD/DA converters, | ||
+ | * real-time clocks, | ||
+ | * sensors (temperature, | ||
+ | * port extenders, | ||
+ | * displays, | ||
+ | * specialised AV circuits. | ||
+ | TWI, as the name says, uses two wires for communication. One is the data line (SDA); the second is the clock line (SCL). Both lines are common to all circuits connected to the one TWI bus. The method of communication of TWI is the master-slave synchronous serial transmission. It means that data is sent bit after bit synchronised with the clock signal. The SCL line is always controlled by the master unit (usually the microcontroller); | ||
+ | At the output side of units, the lines have the open-collector or open-drain circuit. This means that external pullup resistors are needed to ensure the proper operation of the TWI bus. The value of these resistors depends on the number of connected elements, the speed of transmission, | ||
+ | |||
+ | <figure Ref.Pic.2> | ||
+ | {{ : | ||
+ | < | ||
+ | </ | ||
+ | |||
+ | The data is sent using frames of bytes. Every frame begins with a sequence of signals called the start condition. Slaves detect this sequence, which causes them to collect the next eight bits that form the address byte – unique for every circuit on the bus. If one of the slaves recognises its address remains active until the end of the communication frame, others become inactive. To inform the master that some unit has been appropriately addressed slave responses with the acknowledge bit – it generates one bit of low level on the SDA line (the master generates clock pulse). After sending the proper address, data bytes are sent. The direction of the data bytes is controlled by the last bit of the address; for 0, data is transmitted by the master (Write), and for 1, data is sent by the slave (Read). The receiving unit must acknowledge every full byte (eight bits). There is no limitation on the number of data bytes in the frame; for example, samples from the AD converter can be read continuously byte after byte. At the end of the frame, another special sequence is sent by the master–stop condition. It is also possible to generate another start condition without the stop condition. It is called a repeated start condition. | ||
+ | |||
+ | <figure Ref.Pic.3> | ||
+ | {{ : | ||
+ | < | ||
+ | </ | ||
+ | |||
+ | Address byte only activates one chip on the bus, so every unit must have a unique physical address. This byte usually consists of three elements: a 4-bit field fixed by the producer. This 3-bit field can be set by connecting three pins of the chip to 0 (ground) or 1 (power supply line), a 1-bit field for setting the direction of communication (R/#W). Some elements (e.g. EEPROM memory chips) use the 3-bit field for internal addressing, so only one such circuit can be connected to one bus. | ||
+ | There are no special rules for the data bytes. The first data byte sent by the master can be used to configure the slave chip. In memory units, it is used for setting the internal address of the memory for writing or reading in multi-channel AD converters to choose the analogue input. Detailed information on the meaning of every bit of the transmission is present in the documentation of the specific integrated circuit. | ||
+ | The I2C standard also defines the multi-master mode, but in most small projects, there is one master device only. | ||
+ | |||
+ | ===== 1-Wire ===== | ||
+ | 1-Wire is a master-slave communication asynchronous bus interface designed formerly by Dallas Semiconductor Corp((https:// | ||
+ | |||
+ | Each 1-Wire device must contain a logic unit to operate on the bus. A dedicated bus converter is needed to connect a 1-wire bus to a PC. The most popular PC/1-Wire converters use a USB plug to connect to the PC and the RJ11 connectors (telephones 6P2C/6P4C modular plugs) for MicroLAN. 1-Wire devices can also be connected directly to the microcontroller boards. | ||
+ | |||
+ | ==== 1-Wire Protocol Description ==== | ||
+ | Within the MicroLAN, there is always one master device, typically a PC or a microcontroller unit. The master always initiates activity on the bus to avoid collisions on the network chain. If a collision occurs, the master device retries the communication. In the 1-Wire network, many devices can share the same bus line. To identify devices in the MicroLAN, each connected device has a unique 64-bit ID number. The ID number' | ||
+ | The 1-Wire protocol description contains several broadcast commands and commands used to address the selected device. The master sends a selection command, then the address of the selected slave device. This way, the following command is executed only by the addressed device. The 1-Wire bus implements an enumeration procedure that allows the master to get information about the ID numbers of all connected slave devices to the MicroLAN network. The device address includes the device type, identifying what type of slaves are connected to the network chain. The 64-bit address space is searched as a binary tree. It makes it possible to find up to 75 devices per second. | ||
+ | |||
+ | The physical implementation of the 1-Wire network is based on an open drain master device connected to one or more open drain slaves. One single pull-up resistor for all devices pulls the bus up to 3/5 V and can be used to power the slave devices. 1-Wire communication starts when a master or slave sets the bus to low voltage (connects the pull-up resistor to ground through its output MOSFET). | ||
+ | |||
+ | <figure label> | ||
+ | {{ en: | ||
+ | < | ||
+ | </ | ||
+ | |||
+ | The 1-Wire protocol allows for bursting the communication speed up by 10 factors. In this case, the master starts a transmission with a reset pulse, pulling down the data line to 0 volts for at least 480 µs. It resets all slave devices in the network chain bus. Then, any slave device shows it exists, generating the " | ||
+ | |||
+ | To find the devices, the enumeration broadcast command must be sent by a master. The slave device responds with all ID bits to the master, and at the end, it returns a 0. | ||
+ | |||
+ | <figure label> | ||
+ | {{ en: | ||
+ | < | ||
+ | </ | ||
+ | |||
+ | <figure label> | ||
+ | {{ en: | ||
+ | < | ||
+ | </ | ||
+ | |||
+ | <figure label> | ||
+ | {{ en: | ||
+ | < | ||
+ | </ | ||
+ | |||
+ | |||
+ | ==== 1-Wire Products ==== | ||
+ | The Dallas/ | ||
+ | * | ||
+ | * | ||
+ | * | ||
+ | * data loggers, | ||
+ | * | ||
+ | * | ||
+ | * | ||
+ | * | ||
+ | ===== UART ===== | ||
+ | |||
+ | UART name is an abbreviation of Universal Asynchronous Receiver Transmitter. It is one of the most often used communication methods, traditionally named serial interface or serial port. In contrast to previously presented interfaces, UART uses direct point-to-point communication. | ||
+ | UART is the communication unit implemented in microcontrollers rather than the communication protocol. It sends the series of bits via the TxD pin and receives a stream of bits with the RxD pin. It is important to remember that pin TxD from one device should be connected to pin RxD in another device. This is a general rule, but please always check the documentation for some non-standard markings. | ||
+ | |||
+ | <figure label> | ||
+ | {{ en: | ||
+ | < | ||
+ | </ | ||
+ | |||
+ | |||
+ | The transmission speed and bit duration must be the same at the transmitter and receiver to properly transmit data. Although the transmission speed can be freely chosen, some standard, commonly used baud rates exist. They differ from 300 to 115200 bits per second. Higher baud rates are also available in modern microcontrollers, | ||
+ | Start and stop bits are used to synchronise the receiver and transmitter. | ||
+ | |||
+ | <figure label> | ||
+ | {{ en: | ||
+ | < | ||
+ | </ | ||
+ | |||
+ | UART, namely Serial Port, is used in many modern microcontrollers to upload the executable program, debug, and as the standard input/ | ||
+ | < | ||
+ | Many modern PC computers (except industrial ones) do not have a serial port exposed, so USB to serial converters must be used. Some development boards have a USB-serial converter on board (e.g. Arduino Uno, NodeMCU, STM Nucleo, etc.) | ||
+ | </ | ||
+ | < | ||
+ | Even if a PC computer has a serial port, it is usually compatible with the RS-232 standard. It uses the same frame structure but different voltage levels (with opposite zero-one encoding, known as reverse logic). | ||
+ | </ | ||
+ | |||
+ | |||
+ | ====== IoT Hardware Overview ====== | ||
+ | |||
+ | IoT hardware infrastructure is mainly inherited from the embedded systems of the SoC type for Edge class IoT devices and from PCs for Fog class. As IoT devices are by their nature network-enabled, | ||
+ | |||
+ | A microcontroller with network capabilities is the key, but not the only element forming an IoT node device. Additional elements, including sensors and actuators, are needed to keep in touch with the environment. | ||
+ | |||
+ | In the following chapters, there is a description of the families of popular microcontrollers, | ||
+ | * [[en: | ||
+ | * [[en: | ||
+ | * [[en: | ||
+ | |||
+ | Finally, in the last sub-chapter, | ||
+ | * [[en: | ||
+ | |||
+ | |||
+ | ===== Most Noticeable Platforms ===== | ||
+ | The IoT market is an emerging one. New hardware solutions appear almost daily, while others disappear quickly. At the moment of writing the first version of this book (2016-2019), | ||
+ | * AVR: Arduino – a development board using the Atmel microcontroller, | ||
+ | * ESP: Espressif (Espressif Systems) – the great SoC solutions with wireless network interfaces built-in; the family of Espressif chips includes ESP8266 (WiFi) and ESP32 (WiFi, Bluetooth) | ||
+ | * nRF52: Nordic Semiconductor SoC that is based on ARM architecture and offers NFC, Bluetooth and ZigBee capabilities | ||
+ | * STM32: Another ARM-based family of SoCs; some of them have Bluetooth wireless module built-in | ||
+ | * ARM: Raspberry Pi (and its clones) – advanced boards, including Linux operating system with GUI interface, even able to replace desktop computers. | ||
+ | |||
+ | The following chapters are dedicated to the families of the devices, describing their main features: | ||
+ | |||
+ | * [[en: | ||
+ | |||
+ | * [[en: | ||
+ | |||
+ | * [[en: | ||
+ | |||
+ | * [[en: | ||
+ | |||
+ | * [[en: | ||
+ | |||
+ | * [[en: | ||
+ | |||
+ | |||
+ | |||
+ | |||
+ | ===== Sensors and Sensing ===== | ||
+ | |||
+ | A sensor is an element that can turn a physical outer stimulus into an output signal, which can then be used for further analysis, management, or making decisions. People also use sensors like eyes, ears and skin to gain information about the outer world and act according to their aims and needs. Sensors can be divided into many categories according to the measured parameter of the environment. | ||
+ | |||
+ | <figure label> | ||
+ | {{ : | ||
+ | < | ||
+ | </ | ||
+ | |||
+ | Usually, every natural phenomenon – temperature, | ||
+ | |||
+ | * [[en: | ||
+ | |||
+ | * [[en: | ||
+ | |||
+ | * [[en: | ||
+ | |||
+ | * [[en: | ||
+ | |||
+ | * [[en: | ||
+ | |||
+ | * [[en: | ||
+ | |||
+ | * [[en: | ||
+ | |||
+ | * [[en: | ||
+ | |||
+ | ==== Touch Sensors ==== | ||
+ | === Button === | ||
+ | |||
+ | A **pushbutton** is an electromechanical sensor that connects or disconnects two points in a circuit when force is applied. The button output discrete value is either //HIGH// or // | ||
+ | <figure label> | ||
+ | {{ : | ||
+ | < | ||
+ | </ | ||
+ | |||
+ | A **microswitch**, | ||
+ | |||
+ | <figure label> | ||
+ | {{ : | ||
+ | < | ||
+ | </ | ||
+ | |||
+ | The most common use of a pushbutton is as an input device. Both force solutions can be used as simple object detectors or as end switches in industrial devices. The button can be connected to any available digital pin that must be configured as input or input with a pullup. In the configuration presented in the figure below, a pull-up resistor is connected externally, so enabling it in the microcontroller is unnecessary. | ||
+ | |||
+ | <figure label> | ||
+ | {{ : | ||
+ | < | ||
+ | </ | ||
+ | |||
+ | An example code: | ||
+ | <code c> | ||
+ | |||
+ | int buttonPin = 2; // | ||
+ | int buttonState = 0; //A variable for reading the push button status | ||
+ | |||
+ | void setup() { | ||
+ | Serial.begin(9600); | ||
+ | pinMode(buttonPin, | ||
+ | } | ||
+ | |||
+ | void loop() { | ||
+ | //Read the state of the pin where a button is connected | ||
+ | //it is LOW if a button is pressed, HIGH otherwise | ||
+ | //the buttonState variable holds the compliment state of the buttonPin | ||
+ | buttonState = !digitalRead(buttonPin); | ||
+ | //Check if the push button is pressed. If it is, the buttonState variable is HIGH | ||
+ | if (buttonState == HIGH) { | ||
+ | //Print out text in the console | ||
+ | Serial.println(" | ||
+ | } else { | ||
+ | Serial.println(" | ||
+ | } | ||
+ | delay(10); //Delay in between reads for stability | ||
+ | } | ||
+ | |||
+ | </ | ||
+ | |||
+ | ===Force Sensor=== | ||
+ | |||
+ | A force sensor predictably changes resistance depending on the applied force to its surface. Force-sensing resistors are manufactured in different shapes and sizes, and they can measure not only direct force but also tension, compression, | ||
+ | |||
+ | Force sensors are used as control buttons, object presence detectors, or to determine weight in electronic scales. | ||
+ | |||
+ | <figure label> | ||
+ | {{ : | ||
+ | < | ||
+ | </ | ||
+ | |||
+ | <figure label> | ||
+ | {{ : | ||
+ | < | ||
+ | </ | ||
+ | |||
+ | An example code: | ||
+ | <code c> | ||
+ | |||
+ | //Force Sensitive Resistor (FSR) is connected to the analogue 0 pin | ||
+ | int fsrPin = A0; | ||
+ | //The analog reading from the FSR resistor divider | ||
+ | int fsrReading; | ||
+ | |||
+ | void setup(void) { | ||
+ | //Begin serial communication | ||
+ | Serial.begin(9600); | ||
+ | // | ||
+ | pinMode(fsrPin, | ||
+ | } | ||
+ | |||
+ | void loop(void) { | ||
+ | //Read the resistance value of the FSR | ||
+ | fsrReading = analogRead(fsrPin); | ||
+ | // | ||
+ | Serial.print(" | ||
+ | Serial.println(fsrReading); | ||
+ | delay(10); | ||
+ | } | ||
+ | </ | ||
+ | |||
+ | ===Capacitive Sensor=== | ||
+ | Capacitive sensors are a range of sensors that use capacitance to measure changes in the surrounding environment. A capacitive sensor consists of a capacitor that is charged with a certain amount of current until the threshold voltage. A human finger, liquids or other conductive or dielectric materials that touch the sensor can influence the sensor' | ||
+ | |||
+ | Capacitive sensors are used as input devices and can measure proximity, humidity, fluid level and other physical parameters or serve as an input for electronic device control. | ||
+ | |||
+ | <figure label> | ||
+ | {{ : | ||
+ | < | ||
+ | </ | ||
+ | |||
+ | <figure label> | ||
+ | {{ : | ||
+ | < | ||
+ | </ | ||
+ | |||
+ | <code c> | ||
+ | // | ||
+ | int touchPin = 2; | ||
+ | |||
+ | //The variable that stores digital value read from the sensor | ||
+ | boolean touchReading = LOW; | ||
+ | //The variable that stores the previous state of the sensor | ||
+ | boolean lastState = LOW; | ||
+ | |||
+ | void setup() { | ||
+ | //Begin serial communication | ||
+ | Serial.begin(9600); | ||
+ | // | ||
+ | pinMode(touchPin, | ||
+ | } | ||
+ | |||
+ | void loop() { | ||
+ | //Read the digital value of the capacitive sensor | ||
+ | touchReading = digitalRead(touchPin); | ||
+ | //If the new touch has appeared | ||
+ | if (currentState == HIGH && lastState == LOW){ | ||
+ | Serial.println(" | ||
+ | delay(10); //short delay | ||
+ | } | ||
+ | //Save the previous state to see relative changes | ||
+ | lastState = currentState; | ||
+ | } | ||
+ | </ | ||
+ | |||
+ | <note important> | ||
+ | </ | ||
+ | ==== Light Sensors ==== | ||
+ | |||
+ | ===Photoresistor=== | ||
+ | |||
+ | A photoresistor is a sensor that perceives light waves from the environment. The resistance of the photoresistor is changing depending on the intensity of light. The higher the intensity of the light, the lower the sensor' | ||
+ | \\ | ||
+ | <figure label> | ||
+ | {{ : | ||
+ | < | ||
+ | </ | ||
+ | |||
+ | <figure label> | ||
+ | {{ : | ||
+ | < | ||
+ | </ | ||
+ | |||
+ | <figure label> | ||
+ | {{ : | ||
+ | < | ||
+ | </ | ||
+ | |||
+ | Photoresistor connected, as it is shown in the figure above, gives a lower voltage level while the light is more intense. Results can be read with the following example code. The value will be just a number not expressed in any units, e.g. Lux. To express light intensity in luxes, additional calculations must be encoded in the program. | ||
+ | <code c> | ||
+ | //Define an analog A0 pin for photoresistor | ||
+ | int photoresistorPin = A0; | ||
+ | //The analogue reading from the photoresistor | ||
+ | int photoresistorReading; | ||
+ | |||
+ | void setup() | ||
+ | { | ||
+ | //Begin serial communication | ||
+ | Serial.begin(9600); | ||
+ | // | ||
+ | pinMode(photoresistorPin, | ||
+ | } | ||
+ | |||
+ | void loop() | ||
+ | { | ||
+ | //Read the value of the photoresistor | ||
+ | photoresistorReading = analogRead(photoresistorPin); | ||
+ | //Print out the value of the photoresistor reading to the serial monitor | ||
+ | Serial.println(photoresistorReading); | ||
+ | delay(10); //Short delay | ||
+ | } | ||
+ | </ | ||
+ | |||
+ | ===Photodiode=== | ||
+ | A photodiode is a sensor that converts light energy into electrical current. A current in the sensor is generated by exposing a p-n junction of a semiconductor to the light. Information about the light intensity can be determined by measuring a voltage level. Photodiodes react to changes in light intensity very quickly, so they can be used ad receivers of light-based data transmission systems (e.g. fibre data communication). Solar cells are just large photodiodes. | ||
+ | |||
+ | Photodiodes are used as precise light-level sensors, receivers for remote control, electrical isolators (optocouplers), | ||
+ | \\ | ||
+ | <figure label> | ||
+ | {{ : | ||
+ | < | ||
+ | </ | ||
+ | |||
+ | <figure label> | ||
+ | {{ : | ||
+ | < | ||
+ | </ | ||
+ | |||
+ | <figure label> | ||
+ | {{ : | ||
+ | < | ||
+ | </ | ||
+ | Although the photodiode can generate current, the schematic in the figure above shows its connection similar to the photoresistor in the previous example. In such a circuit, the photodiode changes its current according to a change in light intensity, resulting in the voltage change at the microcontroller' | ||
+ | An example code: | ||
+ | <code c> | ||
+ | //Define an analog A0 pin for photodiode | ||
+ | int photodiodePin = A0; | ||
+ | //The analogue reading from the photodiode | ||
+ | int photodiodeReading; | ||
+ | |||
+ | void setup() | ||
+ | { | ||
+ | //Begin serial communication | ||
+ | Serial.begin(9600); | ||
+ | // | ||
+ | pinMode(photodiodePin, | ||
+ | } | ||
+ | |||
+ | void loop() | ||
+ | { | ||
+ | //Read the value of the photodiode | ||
+ | photodiodeReading = analogRead(photodiodePin); | ||
+ | //Print out the value of the photodiode reading to the serial monitor | ||
+ | Serial.println(photodiodeReading); | ||
+ | delay(10); //Short delay | ||
+ | } | ||
+ | </ | ||
+ | |||
+ | ===Phototransistor=== | ||
+ | The phototransistor is a normal bipolar transistor with a transparent enclosure that exposes the base-emitter junction to light. In a bipolar transistor, the current that passes through the collector and emitter depends on the base current. In the phototransistor, | ||
+ | |||
+ | Phototransistors are used as optical switches, proximity sensors and electrical isolators. | ||
+ | \\ | ||
+ | <figure label> | ||
+ | {{ : | ||
+ | < | ||
+ | </ | ||
+ | |||
+ | <figure label> | ||
+ | {{ : | ||
+ | < | ||
+ | </ | ||
+ | |||
+ | <figure label> | ||
+ | {{ : | ||
+ | < | ||
+ | </ | ||
+ | |||
+ | An example code: | ||
+ | <code c> | ||
+ | //Define an analog A1 pin for phototransistor | ||
+ | int phototransistorPin = A1; | ||
+ | //The analogue reading from the phototransistor | ||
+ | int phototransistorReading; | ||
+ | |||
+ | void setup() | ||
+ | { | ||
+ | //Begin serial communication | ||
+ | Serial.begin(9600); | ||
+ | // | ||
+ | pinMode(phototransistorPin, | ||
+ | } | ||
+ | |||
+ | void loop() | ||
+ | { | ||
+ | //Read the value of the phototransistor | ||
+ | phototransistorReading = analogRead(phototransistorPin); | ||
+ | //Print out the value of the phototransistor reading to the serial monitor | ||
+ | Serial.println(phototransistorReading); | ||
+ | delay(10); //short delay | ||
+ | } | ||
+ | </ | ||
+ | |||
+ | ==== Optical Sensors ==== | ||
+ | |||
+ | ===Optocoupler=== | ||
+ | |||
+ | An optocoupler is a device that combines light-emitting and receiving devices in one package. Mostly it is a combination of the infrared light-emitting diode (LED) and a phototransistor. There are three main types of optocouplers: | ||
+ | * an **optocoupler of a closed pair configuration** is enclosed in the dark resin and is used to transfer signals using light. This type of optocoupler is not a sensor itself but is used for ensuring electrical isolation between two circuits; | ||
+ | * a **slotted optocoupler** has an open space between the light source and the sensor; light can be obstructed by external objects and thus can influence the sensor signal. It can be used to detect the presence of flat objects, measure rotation speed, vibrations or serve as a bounce-free switch; | ||
+ | * a **reflective pair configuration**, | ||
+ | \\ | ||
+ | <figure label> | ||
+ | {{ : | ||
+ | < | ||
+ | </ | ||
+ | |||
+ | <figure label> | ||
+ | {{ : | ||
+ | < | ||
+ | </ | ||
+ | |||
+ | <figure label> | ||
+ | {{ : | ||
+ | < | ||
+ | </ | ||
+ | |||
+ | An example code: | ||
+ | <code c> | ||
+ | int optoPin = A0; // | ||
+ | int optoReading; | ||
+ | |||
+ | int objecttreshold = 1000; //Object threshold definition | ||
+ | int whitetreshold = 150; //White colour threshold definition | ||
+ | |||
+ | void setup () | ||
+ | { | ||
+ | //Begin serial communication | ||
+ | Serial.begin(9600); | ||
+ | // | ||
+ | pinMode(optoPin, | ||
+ | } | ||
+ | |||
+ | void loop () | ||
+ | { | ||
+ | optoReading = analogRead(optoPin); | ||
+ | Serial.print ("The reading of the optocoupler sensor is: "); | ||
+ | Serial.println(optoReading); | ||
+ | | ||
+ | //When the reading value is lower than the object threshold | ||
+ | if (optoReading < objecttreshold) { | ||
+ | Serial.println (" | ||
+ | //When the reading value is lower than the white threshold | ||
+ | if (optoReading < white threshold) { | ||
+ | Serial.println (" | ||
+ | } else { //When the reading value is higher than the white threshold | ||
+ | Serial.println (" | ||
+ | } | ||
+ | } | ||
+ | else { //When the reading value is higher than the object threshold | ||
+ | Serial.println (" | ||
+ | } | ||
+ | delay(500); //Short delay | ||
+ | } | ||
+ | </ | ||
+ | |||
+ | ===Colour Sensor=== | ||
+ | This type of sensor gives information about the colour of the light illuminating the sensor surface. Because computers often use RGB (red, green, blue) colour scheme sensor returns three values representing the intensity of three components. Colour sensors usually contain white LEDs to illuminate the surface, which colour should be distinguished by them. The colour sensor uses SPI or TWI interface to send readings. Some models of colour sensors include an additional gesture detector which recognises simple gestures (up, down, left, right). | ||
+ | |||
+ | <figure label> | ||
+ | {{ : | ||
+ | < | ||
+ | </ | ||
+ | |||
+ | <code c> | ||
+ | #include < | ||
+ | #include " | ||
+ | |||
+ | // Example code for the TCS34725 library by Adafruit | ||
+ | |||
+ | // Sensor class | ||
+ | Adafruit_TCS34725 rgb_sensor = Adafruit_TCS34725(); | ||
+ | |||
+ | void setup(void) { | ||
+ | Serial.begin(9600); | ||
+ | |||
+ | if (rgb_sensor.begin()) { // | ||
+ | Serial.println(" | ||
+ | } else { | ||
+ | Serial.println(" | ||
+ | while (1); | ||
+ | } | ||
+ | } | ||
+ | |||
+ | void loop(void) { | ||
+ | uint16_t r, g, b, unfiltered, lux; | ||
+ | |||
+ | rgb_sensor.getRawData(& | ||
+ | lux = rgb_sensor.calculateLux(r, | ||
+ | |||
+ | Serial.print(" | ||
+ | Serial.print(lux, | ||
+ | Serial.print(" | ||
+ | | ||
+ | Serial.print(" | ||
+ | Serial.print(r, | ||
+ | Serial.print(" | ||
+ | | ||
+ | Serial.print(" | ||
+ | Serial.print(g, | ||
+ | Serial.print(" | ||
+ | | ||
+ | Serial.print(" | ||
+ | Serial.print(b, | ||
+ | Serial.print(" | ||
+ | | ||
+ | Serial.print(" | ||
+ | Serial.print(unfiltered, | ||
+ | Serial.println(" | ||
+ | |||
+ | delay(1000); | ||
+ | } | ||
+ | </ | ||
+ | |||
+ | ==== Electrical Characteristic Sensors ==== | ||
+ | Electrical characteristic sensors are used to measure the voltage and amperage of the electric current. When the voltage and current sensors are used concurrently, | ||
+ | |||
+ | ===Voltage Sensor=== | ||
+ | A voltage sensor is a device or circuit for voltage measurement. A simple DC (direct current) voltage sensor consists of a voltage divider circuit with an optional amplifier for a very small voltage measure. For measuring the AC (alternating current), the input is connected to the rectifier diode or bridge to rectify AC to DC and a capacitor to flatten the voltage. The resulting voltage can be measured with an analogue, digital converter of the microcontroller. For safety, while measuring the mains voltage, an optoelectrical isolator should be added at the output, or a transformer to additionally lower the voltage at the input. | ||
+ | |||
+ | A voltage sensor can detect a power failure and measure if the voltage is in the range required. IoT applications include monitoring appliances, power lines, and power supplies. | ||
+ | |||
+ | <figure label> | ||
+ | {{ : | ||
+ | < | ||
+ | </ | ||
+ | |||
+ | <figure label> | ||
+ | {{ : | ||
+ | < | ||
+ | </ | ||
+ | |||
+ | |||
+ | The example code: | ||
+ | |||
+ | <code c> | ||
+ | //Define an analogue A1 pin for voltage sensor | ||
+ | int voltagePin = A1; | ||
+ | //The result of the analogue reading from the voltage sensor | ||
+ | int voltageReading; | ||
+ | |||
+ | float vout = 0.0; | ||
+ | float vin = 0.0; | ||
+ | float R1 = 30000.0; // 30 kΩ resistor | ||
+ | float R2 = 7500.0; // 7.5 kΩ resistor | ||
+ | |||
+ | void setup() | ||
+ | { | ||
+ | //Begin serial communication | ||
+ | Serial.begin(9600); | ||
+ | // | ||
+ | pinMode(voltagePin, | ||
+ | } | ||
+ | |||
+ | void loop() | ||
+ | { | ||
+ | //Read the value of the voltage sensor | ||
+ | voltageReading = analogRead(voltagePin); | ||
+ | vout = (voltageReading * 5.0) / 1024.0; | ||
+ | vin = vout / (R2/ | ||
+ | | ||
+ | Serial.print(" | ||
+ | //Print out the value of the voltage to the serial monitor | ||
+ | Serial.println(vin); | ||
+ | delay(10); //Short delay | ||
+ | } | ||
+ | </ | ||
+ | |||
+ | ===Current Sensor=== | ||
+ | |||
+ | A current sensor is a device or a circuit for current measurement. A simple DC sensor consists of a high-power resistor with low resistance. The current value is obtained by measuring the voltage on the resistor and applying a formula derived from Ohm's law. Other non-invasive measurement methods involve hall effect sensors for DC and AC and inductive coils (current transformer) for AC. Current sensors are used to determine the power consumption and to detect whether the device is turned on or shorted. | ||
+ | |||
+ | < | ||
+ | <figure label> | ||
+ | {{ : | ||
+ | < | ||
+ | </ | ||
+ | |||
+ | <figure label> | ||
+ | {{ : | ||
+ | < | ||
+ | </ | ||
+ | |||
+ | <figure label> | ||
+ | {{ : | ||
+ | < | ||
+ | </ | ||
+ | |||
+ | The example code: | ||
+ | <code c> | ||
+ | //Define an analogue A0 pin for current sensor | ||
+ | const int currentPin = A0; | ||
+ | //Scale factor of the sensor use 100 for 20 A Module and 66 for 30 A Module | ||
+ | int mVperAmp = 185; | ||
+ | int currentReading; | ||
+ | int ACSoffset = 2500; | ||
+ | double Voltage; | ||
+ | double Current; | ||
+ | |||
+ | void setup(){ | ||
+ | | ||
+ | } | ||
+ | |||
+ | void loop(){ | ||
+ | |||
+ | | ||
+ | | ||
+ | | ||
+ | |||
+ | | ||
+ | | ||
+ | | ||
+ | //The ' | ||
+ | | ||
+ | | ||
+ | </ | ||
+ | |||
+ | ==== Proximity and Distance Sensors ==== | ||
+ | |||
+ | ===Infrared Sensor=== | ||
+ | An infrared (IR) proximity sensor is used to detect objects and to measure the distance to them without any physical contact. IR sensor consists of an infrared emitter, a receiving sensor or array of sensors and a signal processing logic. The output of a sensor differs depending on the type – simple proximity detection sensor outputs //HIGH// or //LOW// level when an object is in its sensing range, but sensors which can measure distance output an analogue signal or use some communication protocol, like I2C to send sensor measuring results. | ||
+ | IR sensors are used in robotics to detect obstacles located a few millimetres to several meters from the sensor and in mobile phones to help detect accidental screen touching. | ||
+ | |||
+ | <figure label> | ||
+ | {{ : | ||
+ | < | ||
+ | </ | ||
+ | |||
+ | <figure label> | ||
+ | {{ : | ||
+ | < | ||
+ | </ | ||
+ | |||
+ | An example code: | ||
+ | <code c> | ||
+ | int irPin = A0; //Define an analogue A0 pin for IR sensor | ||
+ | int irReading; | ||
+ | |||
+ | void setup() | ||
+ | { | ||
+ | //Begin serial communication | ||
+ | Serial.begin(9600); | ||
+ | // | ||
+ | pinMode(irPin, | ||
+ | } | ||
+ | |||
+ | void loop() | ||
+ | { | ||
+ | //Read the value of the IR sensor | ||
+ | irReading = analogRead(irPin); | ||
+ | //Print out the value of the IR sensor reading to the serial monitor | ||
+ | Serial.println(irReading); | ||
+ | delay(10); //Short delay | ||
+ | } | ||
+ | </ | ||
+ | |||
+ | ===Ultrasonic Sensor=== | ||
+ | The ultrasonic sensor measures the distance to objects by emitting short ultrasound sound pulse and measuring its returning time. The sensor consists of an ultrasonic emitter and receiver; sometimes, they are combined into a single device for emitting and receiving. Ultrasonic sensors can measure greater distances and cost less than infrared sensors, but are more imprecise and interfere which each other measurement if more than one is used. Simple sensors have a trigger pin and an echo pin; when the trigger pin is set high for a small amount of time, ultrasound is emitted, and on the echo pin, response time is measured. Ultrasonic sensors are used in car parking sensors and robots for proximity detection. | ||
+ | |||
+ | <figure label> | ||
+ | {{ : | ||
+ | < | ||
+ | </ | ||
+ | |||
+ | Examples of IoT applications are robotic obstacle detection and room layout scanning. | ||
+ | |||
+ | <figure label> | ||
+ | {{ : | ||
+ | < | ||
+ | </ | ||
+ | |||
+ | An example code: | ||
+ | <code c> | ||
+ | int trigPin = 2; //Define a trigger pin D2 | ||
+ | int echoPin = 4; //Define an echo pin D4 | ||
+ | |||
+ | void setup() | ||
+ | { | ||
+ | Serial.begin(9600); | ||
+ | pinMode(trigPin, | ||
+ | pinMode(echoPin, | ||
+ | } | ||
+ | |||
+ | void loop() | ||
+ | { | ||
+ | digitalWrite(trigPin, | ||
+ | delayMicroseconds(2); | ||
+ | | ||
+ | //Set the trigPin on HIGH state for 10 μs | ||
+ | digitalWrite(trigPin, | ||
+ | delayMicroseconds(10); | ||
+ | digitalWrite(trigPin, | ||
+ | | ||
+ | //Read the echoPin, return the sound wave travel time in microseconds | ||
+ | duration = pulseIn(echoPin, | ||
+ | // | ||
+ | distance = duration*0.034/ | ||
+ | | ||
+ | //Printing the distance on the Serial Monitor | ||
+ | Serial.print(" | ||
+ | Serial.println(distance); | ||
+ | } | ||
+ | </ | ||
+ | |||
+ | ===Motion Detector=== | ||
+ | The motion detector is a sensor that detects moving objects, mostly people. Motion detectors use different technologies, | ||
+ | |||
+ | Motion sensors are used in security alarm systems, automated lights and door control. As an example in IoT, the PIR motion sensor can be used to detect motion in security systems in a house or any building. | ||
+ | |||
+ | <figure label> | ||
+ | {{ : | ||
+ | < | ||
+ | </ | ||
+ | |||
+ | <figure label> | ||
+ | {{ : | ||
+ | < | ||
+ | </ | ||
+ | |||
+ | An example code: | ||
+ | <code c> | ||
+ | |||
+ | //Passive Infrared (PIR) sensor output is connected to the digital 2 pin | ||
+ | int pirPin = 2; | ||
+ | //The digital reading from the PIR output | ||
+ | int pirReading; | ||
+ | |||
+ | void setup(void) { | ||
+ | //Begin serial communication | ||
+ | Serial.begin(9600); | ||
+ | // | ||
+ | pinMode(pirPin, | ||
+ | } | ||
+ | |||
+ | void loop(void) { | ||
+ | //Read the digital value of the PIR motion sensor | ||
+ | pirReading = digitalRead(pirPin); | ||
+ | //Print out | ||
+ | Serial.print(" | ||
+ | Serial.println(pirReading); | ||
+ | |||
+ | if(pirReading == HIGH) { //Motion was detected | ||
+ | Serial.println(" | ||
+ | } | ||
+ | |||
+ | delay(10); | ||
+ | } | ||
+ | </ | ||
+ | |||
+ | ===Fluid Level Sensor=== | ||
+ | A level sensor detects the level of fluid or fluidised solid. Level sensors can be divided into two groups: | ||
+ | * **continuous level sensors** that can detect the exact position of the fluid. For level detection, usually, the proximity sensors, like ultrasonic or infrared, are used. Capacitive sensors can also be used by recording the changing capacitance value depending on the fluid level. The output can be either analogue or digital value; | ||
+ | * **point-level sensors** can detect whether a fluid is above or below the sensor. A membrane with air pressure or changes in conductivity or capacitance can be used for level detection, also a floating or mechanical switch. The output is usually a digital value that indicates //HIGH// or //LOW// value. | ||
+ | |||
+ | Fluid level sensors can be used for smart waste management, for measuring tank levels, diesel fuel gauging, liquid assets inventory, chemical manufacturing, | ||
+ | |||
+ | <figure label> | ||
+ | {{ : | ||
+ | < | ||
+ | </ | ||
+ | |||
+ | <figure label> | ||
+ | {{ : | ||
+ | < | ||
+ | </ | ||
+ | |||
+ | An example code: | ||
+ | <code c> | ||
+ | int levelPin = 6; //Liquid level sensor output is connected to the digital 6 pin | ||
+ | int levelReading; | ||
+ | |||
+ | void setup(void) { | ||
+ | Serial.begin(9600); | ||
+ | pinMode(levelPin, | ||
+ | } | ||
+ | |||
+ | void loop(void) { | ||
+ | levelReading = digitalRead(levelPin); | ||
+ | Serial.print(" | ||
+ | Serial.println(levelReading); | ||
+ | delay(10); //Short delay | ||
+ | } | ||
+ | </ | ||
+ | |||
+ | ==== Angle & Orientation Sensors ==== | ||
+ | |||
+ | ===Potentiometer=== | ||
+ | A potentiometer is a type of resistor, the resistance of which can be adjusted using a mechanical lever. The device consists of three terminals. The resistor between the first and the third terminal has a fixed value, but the second terminal is connected to the lever. Whenever the lever is turned, a slider of the resistor is moved; it changes the resistance between the second terminal and side terminals. Variable resistance causes the change of the voltage, which can be measured to determine the position of the lever. Thus, the potentiometer output is an analogue value. | ||
+ | |||
+ | Potentiometers are commonly used as a control level, for example, a volume level for the sound and joystick position. They can also be used to determine the angle in feedback loops with motors, such as servo motors. | ||
+ | |||
+ | <figure label> | ||
+ | {{ : | ||
+ | < | ||
+ | </ | ||
+ | |||
+ | <figure label> | ||
+ | {{ : | ||
+ | < | ||
+ | </ | ||
+ | |||
+ | <figure label> | ||
+ | {{ : | ||
+ | < | ||
+ | </ | ||
+ | |||
+ | An example code: | ||
+ | <code c> | ||
+ | |||
+ | // | ||
+ | int potentioPin = A0; | ||
+ | //The analogue reading from the potentiometer output | ||
+ | int potentioReading; | ||
+ | |||
+ | void setup(void) { | ||
+ | //Begin serial communication | ||
+ | Serial.begin(9600); | ||
+ | // | ||
+ | pinMode(potentioPin, | ||
+ | } | ||
+ | |||
+ | void loop(void) { | ||
+ | //Read the analogue value of the potentiometer sensor | ||
+ | potentioReading = analogRead(potentioPin); | ||
+ | Serial.print(" | ||
+ | Serial.println(potentioReading); | ||
+ | delay(10); | ||
+ | } | ||
+ | </ | ||
+ | |||
+ | ===The Inertial Measurement Unit (IMU)=== | ||
+ | |||
+ | An IMU is an electronic device consisting of an accelerometer, | ||
+ | * moving forward/ | ||
+ | * moving left/right, | ||
+ | * moving up/down. | ||
+ | Another three values present the rotation in three axes that can be measured by gyroscope: | ||
+ | * roll side to side, | ||
+ | * pitch forward and backwards, | ||
+ | * yaw left and right. | ||
+ | |||
+ | A **gyroscope** is a sensor that measures the angular velocity. The sensor is made with microelectromechanical system (MEMS) technology and is integrated into the chip. The sensor output can be analogue or digital, using I2C or SPI interface. Gyroscope microchips can vary in the number of axes they can measure. The available number of the axis is 1, 2 or 3 axes in the gyroscope. A gyroscope is commonly used with an accelerometer to precisely determine the device' | ||
+ | Gyroscope sensors are used in aviation, navigation and motion control. | ||
+ | |||
+ | An **accelerometer** measures the acceleration of the object. The sensor uses microelectromechanical system (MEMS) technology, where capacitive plates are attached to springs. When acceleration force is applied to the plates, the capacitance is changed; thus, it can be measured. Accelerometers can have 1 to 3 axis. The 3-axis accelerometer can detect the device' | ||
+ | Accelerometers are used to measure objects' | ||
+ | |||
+ | A **magnetometer** is a sensor that can measure the device' | ||
+ | |||
+ | There are different elements available that allow measuring linear accelerations, | ||
+ | |||
+ | < | ||
+ | <figure label> | ||
+ | {{ : | ||
+ | < | ||
+ | </ | ||
+ | |||
+ | < | ||
+ | <figure label> | ||
+ | {{ : | ||
+ | < | ||
+ | </ | ||
+ | |||
+ | <figure label> | ||
+ | {{ : | ||
+ | < | ||
+ | </ | ||
+ | |||
+ | <figure label> | ||
+ | {{ : | ||
+ | < | ||
+ | </ | ||
+ | |||
+ | The example code: | ||
+ | <code c> | ||
+ | //Library for I2C communication | ||
+ | #include < | ||
+ | // | ||
+ | #include < | ||
+ | // | ||
+ | #include < | ||
+ | #include < | ||
+ | Adafruit_BNO055 bno = Adafruit_BNO055(55); | ||
+ | void setup(void) | ||
+ | { | ||
+ | bno.setExtCrystalUse(true); | ||
+ | } | ||
+ | void loop(void) | ||
+ | { | ||
+ | //Read sensor data | ||
+ | sensors_event_t event; | ||
+ | bno.getEvent(& | ||
+ | //Print X, Y And Z orientation | ||
+ | Serial.print(" | ||
+ | Serial.print(event.orientation.x, | ||
+ | Serial.print(" | ||
+ | Serial.print(event.orientation.y, | ||
+ | Serial.print(" | ||
+ | Serial.print(event.orientation.z, | ||
+ | Serial.println("" | ||
+ | delay(100); | ||
+ | } | ||
+ | |||
+ | </ | ||
+ | |||
+ | ==== Environment Sensors ==== | ||
+ | |||
+ | ===Temperature Sensor=== | ||
+ | A temperature sensor is a device that is used to determine the temperature of the surrounding environment. Most temperature sensors work on the principle that the material' | ||
+ | * **thermocouple** – consists of two junctions of dissimilar metals, | ||
+ | * **thermistor** – includes the temperature-dependent resistor, | ||
+ | * **resistive temperature detector** – is made of a pure metal coil. | ||
+ | The main difference between sensors is the measured temperature range, precision and response time. Temperature sensor usually outputs the analogue value, but some existing sensors have a digital interface ((http:// | ||
+ | |||
+ | Temperature sensors are most commonly used in environmental monitoring devices and thermoelectric switches. In IoT applications, | ||
+ | |||
+ | <figure label> | ||
+ | {{ : | ||
+ | < | ||
+ | </ | ||
+ | |||
+ | <figure label> | ||
+ | {{ : | ||
+ | < | ||
+ | </ | ||
+ | |||
+ | An example code: | ||
+ | <code c> | ||
+ | |||
+ | // | ||
+ | int thermoPin = 0; | ||
+ | //The analogue reading from the thermistor output | ||
+ | int thermoReading; | ||
+ | |||
+ | void setup(void) { | ||
+ | //Begin serial communication | ||
+ | Serial.begin(9600); | ||
+ | // | ||
+ | pinMode(thermoPin, | ||
+ | } | ||
+ | |||
+ | void loop(void) { | ||
+ | //Read the analogue value of the thermistor sensor | ||
+ | thermoReading = analogRead(thermoPin); | ||
+ | Serial.print(" | ||
+ | Serial.println(thermoReading); | ||
+ | delay(10); | ||
+ | } | ||
+ | </ | ||
+ | |||
+ | ===Digital Temperature Sensor=== | ||
+ | Digital temperature sensors automatically convert the temperature reading into some known unit, e.g. Celsius, Fahrenheit or Kelvin Degrees. Digital thermometers use one of the popular communication links. An example of a digital thermometer is DS18B20 by Dallas Semiconductors. It uses a 1-Wire communication protocol. | ||
+ | |||
+ | < | ||
+ | **DS18B20 photo** | ||
+ | < | ||
+ | **DS18B20 connection** | ||
+ | |||
+ | <code c> | ||
+ | #include < | ||
+ | #include < | ||
+ | |||
+ | const int SENSOR_PIN = 13; // | ||
+ | |||
+ | OneWire oneWire(SENSOR_PIN); | ||
+ | DallasTemperature tempSensor(& | ||
+ | |||
+ | float tempCelsius; | ||
+ | |||
+ | void setup() | ||
+ | { | ||
+ | Serial.begin(9600); | ||
+ | tempSensor.begin(); | ||
+ | } | ||
+ | |||
+ | void loop() | ||
+ | { | ||
+ | tempSensor.requestTemperatures(); | ||
+ | tempCelsius = tempSensor.getTempCByIndex(0); | ||
+ | |||
+ | Serial.print(" | ||
+ | Serial.print(tempCelsius); | ||
+ | Serial.println(" | ||
+ | |||
+ | delay(1000); | ||
+ | } | ||
+ | |||
+ | </ | ||
+ | |||
+ | ===Humidity Sensor=== | ||
+ | A humidity sensor (hygrometer) is a sensor that detects the amount of water or water vapour in the environment. The most common principle of air humidity sensors is the change of capacitance or resistance of materials that absorb moisture from the environment. Soil humidity sensors measure the resistance between the two electrodes. The resistance between electrodes is influenced by soluble salts and water amounts in the soil. The output of a humidity sensor is an analogue signal value or digital value sent with some popular protocols ((https:// | ||
+ | |||
+ | Examples of IoT applications are monitoring of humidors, greenhouse humidity, agriculture, | ||
+ | |||
+ | <figure label> | ||
+ | {{ : | ||
+ | < | ||
+ | </ | ||
+ | |||
+ | <figure label> | ||
+ | {{ : | ||
+ | < | ||
+ | </ | ||
+ | |||
+ | An example code ((http:// | ||
+ | <code c> | ||
+ | #include < | ||
+ | |||
+ | dht DHT; | ||
+ | |||
+ | #define DHT_PIN 7 | ||
+ | |||
+ | void setup(){ | ||
+ | Serial.begin(9600); | ||
+ | } | ||
+ | |||
+ | void loop() | ||
+ | { | ||
+ | int chk = DHT.read11(DHT_PIN); | ||
+ | Serial.print(" | ||
+ | Serial.println(DHT.humidity); | ||
+ | delay(1000); | ||
+ | } | ||
+ | </ | ||
+ | |||
+ | ===Sound Sensor=== | ||
+ | A sound sensor is a sensor that detects vibrations in a gas, liquid or solid environment. At first, the sound wave pressure makes mechanical vibrations, which transfer to changes in capacitance, | ||
+ | |||
+ | Sound sensors are used in drone detection, gunshot alert, seismic detection and vault safety alarms. | ||
+ | |||
+ | <figure label> | ||
+ | {{ : | ||
+ | < | ||
+ | </ | ||
+ | |||
+ | <figure label> | ||
+ | {{ : | ||
+ | < | ||
+ | </ | ||
+ | |||
+ | An example code: | ||
+ | <code c> | ||
+ | //Sound sensor output is connected to the digital 7 pin | ||
+ | int soundPin = 7; | ||
+ | //Stores sound sensor detection readings | ||
+ | int soundReading = HIGH; | ||
+ | |||
+ | void setup(void) { | ||
+ | //Begin serial communication | ||
+ | Serial.begin(9600); | ||
+ | // | ||
+ | pinMode(soundPin, | ||
+ | } | ||
+ | |||
+ | void loop(void) { | ||
+ | //Read the digital value whether the sound has been detected | ||
+ | soundReading = digitalRead(soundPin); | ||
+ | if (soundPin==LOW) { //When sound detector detected the sound | ||
+ | Serial.println(" | ||
+ | } else { //When the sound is not detected | ||
+ | Serial.println(" | ||
+ | } | ||
+ | delay(10); | ||
+ | } | ||
+ | </ | ||
+ | |||
+ | |||
+ | ===Chemical and Gas Sensor=== | ||
+ | Gas sensors are a sensor group that can detect and measure the concentration of certain gasses in the air. The working principle of electrochemical sensors is to absorb the gas and create current from an electrochemical reaction. For process acceleration, | ||
+ | The smoke or air pollution sensors usually use LED or laser that emits light and a detector which is normally shaded from the light. If there are particles of smoke or polluted air inside the sensor, the light is reflected by them, which can be observed by the detector. | ||
+ | |||
+ | Gas sensors are used for safety devices, air quality control, and manufacturing equipment. IoT applications include air quality control management in smart buildings and smart cities or toxic gas detection in sewers and underground mines. | ||
+ | |||
+ | <figure label> | ||
+ | {{ : | ||
+ | < | ||
+ | </ | ||
+ | |||
+ | <figure label> | ||
+ | {{ : | ||
+ | < | ||
+ | </ | ||
+ | |||
+ | An example code: | ||
+ | <code c> | ||
+ | int gasPin = A0; //Gas sensor output is connected to the analog A0 pin | ||
+ | int gasReading; //Stores gas sensor detection reading | ||
+ | |||
+ | void setup(void) { | ||
+ | Serial.begin(9600); | ||
+ | pinMode(gasPin, | ||
+ | } | ||
+ | |||
+ | void loop(void) { | ||
+ | gasReading = analogRead(gasPin); | ||
+ | Serial.print(" | ||
+ | Serial.println(gasReading); | ||
+ | delay(10); //Short delay | ||
+ | } | ||
+ | </ | ||
+ | |||
+ | ===Smoke and Air Pollution Sensors=== | ||
+ | The smoke sensors usually emit LED light, and a detector is normally shaded from the light. If there are particles of smoke present inside the sensor, the light is reflected by them, which can be observed by the detector. | ||
+ | Smoke detectors are used in fire alarm systems. | ||
+ | The air pollution sensors usually use a laser directed onto the detector. Between the laser and detector, the thin stream of air flows and pollution particles create shades on the detector. Thus the detector can distinguish the sizes of particles and count the number of them. | ||
+ | Air pollution sensors are used in air purifiers and in air quality measurement stations to monitor current air conditions, mainly in cities. Because the air pollution sensor generates more data, the serial connection is often used for reading measurement results. An example of an air pollution sensor that can count particles of PM1.0, PM2.5, and PM10 is PMS5003. | ||
+ | |||
+ | < | ||
+ | **PMS5003 photo** | ||
+ | < | ||
+ | **PMS5003 connection** | ||
+ | |||
+ | An example code that uses the PMS5003 sensor: | ||
+ | <code c> | ||
+ | |||
+ | #define length 31 // | ||
+ | //(does not include the start indicator - 0x42) | ||
+ | unsigned char buffer[length]; | ||
+ | |||
+ | int PM_1_0=0; | ||
+ | int PM_2_5=0; | ||
+ | int PM_10=0; | ||
+ | |||
+ | void setup() | ||
+ | { | ||
+ | // | ||
+ | Serial.begin(9600); | ||
+ | } | ||
+ | |||
+ | void loop() | ||
+ | { | ||
+ | if(Serial.find(0x42)) //detecting 0x42 means start of data frame from sensor | ||
+ | { | ||
+ | Serial.readBytes(buffer, | ||
+ | if(buffer[0] == 0x4d) | ||
+ | { | ||
+ | PM_1_0=((buffer[3]<< | ||
+ | PM_2_5=((buffer[5]<< | ||
+ | PM_10 =((buffer[7]<< | ||
+ | | ||
+ | Serial.print(" | ||
+ | Serial.print(PM_1_0); | ||
+ | Serial.println(" | ||
+ | | ||
+ | Serial.print(" | ||
+ | Serial.print(PM_2_5); | ||
+ | Serial.println(" | ||
+ | | ||
+ | Serial.print(" | ||
+ | Serial.print(PM_10); | ||
+ | Serial.println(" | ||
+ | } | ||
+ | } | ||
+ | } | ||
+ | </ | ||
+ | |||
+ | ===Air Pressure Sensor=== | ||
+ | Air pressure sensors can measure the absolute pressure in the surrounding environment. Some popular sensors use a piezo-resistive sensing element which is then connected to the amplifier and analogue, digital converter. Frint-end uses the logic to interface the microcontroller. Usually, barometric sensor readings depend on the temperature, | ||
+ | Popular examples of barometric sensors are BME280 and BMP280. Both include barometric sensors and temperature sensors built in for compensation and possible measurement, | ||
+ | Communication with these sensors is done with I2C or SPI bus. | ||
+ | |||
+ | Barometric sensors are used in weather stations, home automation for heating, venting, air conditioning (HVAC), and airflow measurement. Because air pressure varies with altitude, they are often used in altimeters. | ||
+ | |||
+ | < | ||
+ | **BME280 photo** | ||
+ | < | ||
+ | **BME280 connection** | ||
+ | |||
+ | An example code of BME280 use is below ((https:// | ||
+ | <code c> | ||
+ | #include < | ||
+ | #include < | ||
+ | |||
+ | Bme280TwoWire sensor; | ||
+ | |||
+ | void setup() { | ||
+ | Serial.begin(9600); | ||
+ | Wire.begin(D2, | ||
+ | |||
+ | Serial.println(); | ||
+ | |||
+ | sensor.begin(Bme280TwoWireAddress:: | ||
+ | sensor.setSettings(Bme280Settings:: | ||
+ | } | ||
+ | |||
+ | void loop() { | ||
+ | auto temperature = String(sensor.getTemperature()) + " °C"; | ||
+ | auto pressure = String(sensor.getPressure() / 100.0) + " hPa"; | ||
+ | auto humidity = String(sensor.getHumidity()) + " %"; | ||
+ | |||
+ | String measurements = temperature + ", " + pressure + ", " + humidity; | ||
+ | Serial.println(measurements); | ||
+ | |||
+ | delay(10000); | ||
+ | } | ||
+ | </ | ||
+ | |||
+ | |||
+ | ==== Other Sensors ==== | ||
+ | |||
+ | ===Hall sensor=== | ||
+ | A **Hall effect sensor** detects strong magnetic fields, their polarities and the relative strength of the field. In the Hall effect sensors, a magnetic force influences current flow through the semiconductor material and creates a measurable voltage on the sides of the semiconductor. Sensors with analogue output can measure the strength of the magnetic field, while digital sensors give //HIGH// or //LOW// output value, depending on the presence of the magnetic field. | ||
+ | |||
+ | Hall effect sensors are used in magnetic encoders for speed and rotation measurements. They can replace mechanical switches in keyboards and proximity switches because they do not require contact, which ensures high reliability. An example application can be sensing the position of rotary valves. | ||
+ | |||
+ | <figure label> | ||
+ | {{ : | ||
+ | < | ||
+ | </ | ||
+ | |||
+ | <figure label> | ||
+ | {{ : | ||
+ | < | ||
+ | </ | ||
+ | |||
+ | The example code: | ||
+ | <code c> | ||
+ | int hallPin = A0; //Hall sensor output is connected to the analogue A0 pin | ||
+ | int hallReading; | ||
+ | |||
+ | void setup(void) { | ||
+ | Serial.begin(9600); | ||
+ | pinMode(hallPin, | ||
+ | } | ||
+ | |||
+ | void loop(void) { | ||
+ | hallReading = analogRead(hallPin); | ||
+ | Serial.print(" | ||
+ | Serial.println(hallReading); | ||
+ | delay(10); //Short delay | ||
+ | } | ||
+ | </ | ||
+ | |||
+ | ===Global Positioning System=== | ||
+ | A GPS receiver is a device that can receive information from a global navigation satellite system and calculate its position on the Earth. A GPS receiver uses a constellation of satellites and ground stations to compute position and time almost anywhere on Earth. GPS receivers are used for navigation only in the outdoor area because they need to receive signals from the satellites, which is difficult inside the buildings. The GPS location' | ||
+ | |||
+ | A GPS receiver is used for device location tracking. Real applications might be, e.g., pet, kid or personal belonging location tracking. | ||
+ | |||
+ | <figure label> | ||
+ | {{ : | ||
+ | < | ||
+ | </ | ||
+ | |||
+ | |||
+ | <figure label> | ||
+ | {{ : | ||
+ | < | ||
+ | </ | ||
+ | |||
+ | The example code ((http:// | ||
+ | <code c> | ||
+ | #include < | ||
+ | SoftwareSerial SoftSerial(2, | ||
+ | unsigned char buffer[64]; | ||
+ | int count=0; | ||
+ | void setup() | ||
+ | { | ||
+ | SoftSerial.begin(9600); | ||
+ | Serial.begin(9600); | ||
+ | } | ||
+ | |||
+ | void loop() | ||
+ | { | ||
+ | if (SoftSerial.available()) | ||
+ | // ==> Data is coming from SoftSerial shield | ||
+ | { | ||
+ | while(SoftSerial.available()) | ||
+ | { | ||
+ | buffer[count++]=SoftSerial.read(); | ||
+ | if(count == 64)break; | ||
+ | } | ||
+ | Serial.write(buffer, | ||
+ | // | ||
+ | clearBufferArray(); | ||
+ | //The stored data from the array | ||
+ | count = 0; //Set the counter of the while loop to zero | ||
+ | } | ||
+ | if (Serial.available()) | ||
+ | // ==> Data is coming from a PC or notebook | ||
+ | SoftSerial.write(Serial.read()); | ||
+ | } | ||
+ | |||
+ | |||
+ | void clearBufferArray() | ||
+ | { | ||
+ | for (int i=0; i< | ||
+ | { | ||
+ | buffer[i]=NULL; | ||
+ | } // | ||
+ | } | ||
+ | </ | ||
+ | ===== Actuators and output devices ===== | ||
+ | |||
+ | An output device is a unit that changes an electrical signal coming from the microcontroller into the physical parameter. It can generate or modify light, sound, force, pressure and other physical values that influence other devices nearby or the surrounding environment. Some output elements can be connected directly to the microcontroller' | ||
+ | |||
+ | * [[en: | ||
+ | |||
+ | * [[en: | ||
+ | |||
+ | * [[en: | ||
+ | | ||
+ | * [[en: | ||
+ | ==== Optical Output Devices ==== | ||
+ | |||
+ | === Light-Emitting Diode === | ||
+ | Unlike the other diodes, the light-emitting diode, also called LED, is a special type that emits light. LED has a completely different body which is made of transparent plastic that protects the diode and lets it emit light. Like the other diodes, LED conducts the current in only one way, so connecting it to the scheme is essential. There are two safe ways how to determine the direction of the diode: | ||
+ | * in the cathodes side of the diode its side is chipped, | ||
+ | * anodes leg usually is longer than the cathodes leg. | ||
+ | |||
+ | <figure label> | ||
+ | {{ : | ||
+ | < | ||
+ | </ | ||
+ | |||
+ | The LED is one of the most efficient light sources. Unlike incandescent light bulbs, LED transforms most of the power into light, not warmth; it is more durable, works for a more extended period and can be manufactured in a smaller size. | ||
+ | |||
+ | The LED colour is determined by the semiconductors material. Diodes are usually made from silicon, then LEDs are made from elements like gallium phosphate, silicon carbide and others. Because the semiconductors used are different, the voltage needed for the LED to shine is also different. | ||
+ | |||
+ | When the LED is connected to the voltage and turned on, a huge current starts to flow through it, and it can damage the diode. That is why all **LEDs have to be connected in series with a current-limiting resistor**. | ||
+ | |||
+ | Current limiting resistors resistance is determined by three parameters: | ||
+ | * //I_D// – Current that can flow through the LED, | ||
+ | * //U_D// – Voltage that is needed to turn on the LED, | ||
+ | * //U// – Combined voltage for LED and resistor. | ||
+ | |||
+ | To calculate the resistance needed for a diode, this is what you have to do. | ||
+ | - Find out the voltage needed for the diode to work //U_D//; you can find it in the diode parameters table. | ||
+ | - Find out the amperage needed for the LED to shine //I_D//; it can be found in the LEDs datasheet, but if you can’t find it, then 20 mA current is usually a correct and safe choice. | ||
+ | - Find out the combined voltage for the LED and resistor; usually, it is the feeding voltage for the scheme. | ||
+ | - Insert all the values into this equation: //R = (U – U_D) / I_D// | ||
+ | - You get the resistance for the resistor for the safe use of the LED. | ||
+ | - Find a resistor with a nominal value that is the same or slightly bigger than the calculated resistance. | ||
+ | |||
+ | <figure label> | ||
+ | {{ : | ||
+ | < | ||
+ | </ | ||
+ | |||
+ | An example of the blinking LED code: | ||
+ | <code c> | ||
+ | int ledPin = 8;// | ||
+ | |||
+ | void setup() | ||
+ | { | ||
+ | pinMode(ledPin, | ||
+ | } | ||
+ | |||
+ | void loop() | ||
+ | { | ||
+ | //Set pin output signal to HIGH – LED is working | ||
+ | digitalWrite(ledPin, | ||
+ | //Belay of 1000 ms | ||
+ | delay(1000); | ||
+ | |||
+ | //Set pin output signal to LOW – LED is not working | ||
+ | digitalWrite(ledPin, | ||
+ | //Delay of 1000 ms | ||
+ | delay(1000); | ||
+ | } | ||
+ | </ | ||
+ | |||
+ | LED's brightness can be controlled with a PWM signal as described in the " | ||
+ | There exist LEDs with more than one light-emitting chip in one enclosure. They are made as two-coloured or RGB elements with coloured controlled separately. There are two internal configurations of such elements: | ||
+ | * common anode - anodes of all internal LEDs are connected together | ||
+ | * common cathode - cathodes of all internal LEDs are connected | ||
+ | |||
+ | <figure label> | ||
+ | {{ : | ||
+ | < | ||
+ | </ | ||
+ | |||
+ | <figure label> | ||
+ | {{ : | ||
+ | < | ||
+ | </ | ||
+ | |||
+ | <todo # | ||
+ | |||
+ | === Digital LED === | ||
+ | < | ||
+ | Digital LED does not have anode or cathode connections available externally. They have power supply pins and two pins for data transmission, | ||
+ | |||
+ | === Displays === | ||
+ | |||
+ | Using a display is a quick way to get feedback information from the device. There are many display technologies. For IoT solutions, low-power, easy-to-use displays are used: | ||
+ | * 7-segment LED display | ||
+ | * LED matrix display | ||
+ | * liquid-crystal display (LCD), | ||
+ | * organic light-emitting diode display (OLED), | ||
+ | * electronic ink display (E-ink). | ||
+ | |||
+ | **7-segment LED display** | ||
+ | <todo # | ||
+ | The seven-segment LED display is built with seven LEDs forming the shape that makes it possible to display symbols similar to digits, and even some letters. Usually, the eighth LED is added as the decimal point. 7-segment displays can have similar internal connections as RGB LEDs, common anode or common cathode. If there is more than one digit in the element all the same segments are also connected together. Such displays need special controllers or the part of the software that displays separate digits in a sequence one by one. To avoid unnecessary blinking or difference in the brightness of digits, software for sequential displays is written with the use of timers and interrupts. As for the RGB LEDs, 7-segment displays need a separate resistor for every segment. | ||
+ | |||
+ | <figure label> | ||
+ | {{ : | ||
+ | < | ||
+ | </ | ||
+ | |||
+ | |||
+ | **LED matrix display** | ||
+ | <todo # | ||
+ | LED matrix displays offer the possibility of displaying not only digits and letters but also some pictograms and symbols. The most popular versions have 8 rows and 8 columns, or 7 rows and 5 columns, but it is possible to find other configurations. As for the 7-segment displays, there are common anode and common cathode configurations. For a common anode, all anodes in one row and all cathodes in one column are connected together. For a common cathode, all cathodes in one row and all anodes in one column are connected together. Modern LED matrix displays have built-in controllers or are made with the use of digital RGB LEDs which makes them possible to display pictures and even videos. | ||
+ | |||
+ | < | ||
+ | |||
+ | **Liquid-Crystal Display (LCD)** | ||
+ | |||
+ | Monochrome LCD uses modulating properties of liquid crystal to block the passing-through light. Thus when a voltage is applied to a pixel, it is dark. A display consists of layers of electrodes, polarising filters, liquid crystals and a reflector or back-light. Liquid crystals do not emit light directly but through reflection or backlight. Because of this reason, they are more energy efficient. Small, monochrome LCDs are widely used in devices to show a little numerical or textual information like temperature, | ||
+ | |||
+ | <figure label> | ||
+ | {{ : | ||
+ | < | ||
+ | </ | ||
+ | |||
+ | <figure label> | ||
+ | {{ : | ||
+ | < | ||
+ | </ | ||
+ | |||
+ | The example code: | ||
+ | <code c> | ||
+ | #include < | ||
+ | |||
+ | //Define LCD pins | ||
+ | const int rs = 12, en = 11, d4 = 5, d5 = 4, d6 = 3, d7 = 2; | ||
+ | //Create an LCD object with predefined pins | ||
+ | LiquidCrystal lcd(rs, en, d4, d5, d6, d7); | ||
+ | |||
+ | void setup() { | ||
+ | lcd.begin(16, | ||
+ | lcd.print(" | ||
+ | } | ||
+ | |||
+ | void loop() { | ||
+ | //Set the cursor to column 0, line 1 – line 1 is the second row | ||
+ | //Since counting begins with 0 | ||
+ | lcd.setCursor(0, | ||
+ | //Print the number of seconds since the reset | ||
+ | lcd.print(millis() / 1000); | ||
+ | } | ||
+ | </ | ||
+ | |||
+ | **Organic Light-Emitting Diode Display (OLED)** | ||
+ | |||
+ | OLED display uses electroluminescent materials that emit light when the current passes through these materials. The display consists of two electrodes and a layer of an organic compound. OLED displays are thinner than LCDs, have higher contrast, and can be more energy efficient depending on usage. OLED displays are commonly used in mobile devices like smartwatches and cell phones, and they are replacing LCDs in other devices. OLED displays come as monochrome or RGB colour devices. Small OLED display modules usually have an onboard control circuit that uses digital interfaces like I2C or SPI. | ||
+ | |||
+ | <figure label> | ||
+ | {{ : | ||
+ | < | ||
+ | </ | ||
+ | |||
+ | <figure label> | ||
+ | {{ : | ||
+ | < | ||
+ | </ | ||
+ | |||
+ | <code c> | ||
+ | //Add libraries to ensure the functioning of OLED | ||
+ | #include < | ||
+ | #include < | ||
+ | #include < | ||
+ | #define OLED_RESET 4 | ||
+ | Adafruit_SSD1306 display(OLED_RESET); | ||
+ | |||
+ | void setup() { | ||
+ | //Setting up initial OLED parameters | ||
+ | display.begin(SSD1306_SWITCHCAPVCC, | ||
+ | display.setTextSize(1); | ||
+ | display.setTextColor(WHITE); | ||
+ | |||
+ | void loop() { | ||
+ | |||
+ | //Print out on display output sensor values | ||
+ | display.setCursor(0, | ||
+ | display.clearDisplay(); | ||
+ | display.print(" | ||
+ | display.display(); | ||
+ | delay(100); | ||
+ | display.clearDisplay(); | ||
+ | } | ||
+ | </ | ||
+ | |||
+ | |||
+ | **Electronic Ink Display (E-Ink)** | ||
+ | |||
+ | E-ink display uses charged particles to create a paper-like effect. The display comprises transparent microcapsules filled with oppositely charged white and black particles between electrodes. Charged particles change their location depending on the orientation of the electric field; thus, individual pixels can be either black or white. The image does not need power to persist on the screen; power is used only when the image is changed. Thus e-ink display is very energy efficient. It has high contrast and viewing angle but a low refresh rate. E-ink displays are commonly used in e-readers, smartwatches, | ||
+ | |||
+ | <figure label> | ||
+ | {{ : | ||
+ | < | ||
+ | </ | ||
+ | |||
+ | <figure label> | ||
+ | {{ : | ||
+ | < | ||
+ | </ | ||
+ | |||
+ | <code c> | ||
+ | #include < | ||
+ | #include < | ||
+ | |||
+ | E_ink Eink; | ||
+ | |||
+ | void setup() | ||
+ | { | ||
+ | //BS LOW for 4 line SPI | ||
+ | pinMode(8, | ||
+ | digitalWrite(8, | ||
+ | | ||
+ | Eink.InitEink(); | ||
+ | |||
+ | Eink.ClearScreen();// | ||
+ | |||
+ | Eink.EinkP8x16Str(14, | ||
+ | Eink.EinkP8x16Str(10, | ||
+ | Eink.EinkP8x16Str(6, | ||
+ | Eink.EinkP8x16Str(2, | ||
+ | |||
+ | Eink.RefreshScreen(); | ||
+ | } | ||
+ | void loop() | ||
+ | { | ||
+ | |||
+ | } | ||
+ | </ | ||
+ | <todo @pczekalski> | ||
+ | ==== Electromechanical Devices ==== | ||
+ | |||
+ | === Relay === | ||
+ | |||
+ | Relays are electromechanical devices that use electromagnets to connect or disconnect the plates of a switch. Relays are used to control high-power circuits with low-power circuits. Circuits are electrically isolated and thus protect logic control. Relays are used in household appliance automation, lighting and climate control. Although the electromagnet' | ||
+ | |||
+ | <figure label> | ||
+ | {{ : | ||
+ | < | ||
+ | </ | ||
+ | |||
+ | <figure label> | ||
+ | {{ : | ||
+ | < | ||
+ | </ | ||
+ | |||
+ | The example code: | ||
+ | <code c> | ||
+ | #define relayPin | ||
+ | | ||
+ | void setup() | ||
+ | { | ||
+ | Serial.begin(9600); | ||
+ | pinMode(relayPin, | ||
+ | |||
+ | } | ||
+ | |||
+ | void loop() | ||
+ | { | ||
+ | | ||
+ | | ||
+ | | ||
+ | |||
+ | | ||
+ | | ||
+ | | ||
+ | } | ||
+ | </ | ||
+ | |||
+ | === Solenoid === | ||
+ | Solenoids are devices that use electromagnets to pull or push iron or steel core. They are used as linear actuators for locking mechanisms indoors, pneumatic and hydraulic valves and in-car starter systems. | ||
+ | |||
+ | Solenoids and relays both use electromagnets, | ||
+ | |||
+ | <figure label> | ||
+ | {{ : | ||
+ | < | ||
+ | </ | ||
+ | |||
+ | <figure label> | ||
+ | {{ : | ||
+ | < | ||
+ | </ | ||
+ | |||
+ | The example code: | ||
+ | <code c> | ||
+ | #define solenoidPin | ||
+ | | ||
+ | void setup() | ||
+ | { | ||
+ | Serial.begin(9600); | ||
+ | pinMode(solenoidPin, | ||
+ | |||
+ | } | ||
+ | |||
+ | void loop() | ||
+ | { | ||
+ | | ||
+ | | ||
+ | | ||
+ | |||
+ | | ||
+ | | ||
+ | | ||
+ | } | ||
+ | </ | ||
+ | |||
+ | ==== Sound Output Devices ==== | ||
+ | |||
+ | === Speaker === | ||
+ | Speakers are electroacoustic devices that convert electrical signals into sound waves. A speaker uses a permanent magnet and a coil attached to the membrane. Sound signal, flowing through the coil, creates the electromagnetic field with variable strength; coil attracts to magnet according to the strength of the field, thus making a membrane vibrate and creating a sound wave. Another widely used speaker technology, called piezo speaker, uses piezoelectric materials instead of magnets. Speakers are used to create an audible sound for human perception and ultrasonic sound for sensors and measurement equipment. Some speakers are created to generate acoustic tones of a single, fixed frequency. Such elements are called buzzers and have a built-in generator to emit sound if the voltage is on. Elements without built-in generators should be controlled with the frequency signal coming from the microcontroller. Sound-generating devices require more power than LED, so there is a need to check if the operating current is lower than the maximum current of the microcontroller' | ||
+ | |||
+ | <figure label> | ||
+ | {{ : | ||
+ | < | ||
+ | </ | ||
+ | |||
+ | <figure label> | ||
+ | {{ : | ||
+ | < | ||
+ | </ | ||
+ | |||
+ | <code c> | ||
+ | const int speakerPin = 9; //Define the piezo speaker pin | ||
+ | |||
+ | void setup() | ||
+ | { | ||
+ | pinMode(speakerPin, | ||
+ | } | ||
+ | |||
+ | void loop() | ||
+ | { | ||
+ | tone(speakerrPin, | ||
+ | delay(1000); | ||
+ | noTone(speakerPin); | ||
+ | delay(1000); | ||
+ | } | ||
+ | </ | ||
+ | |||
+ | ==== Actuators ==== | ||
+ | |||
+ | Actuators are devices that can do a physical action to the surrounding world. Most actuators are based on one of the forms of electric motors, sometimes directly, sometimes using a gearbox and advanced control logic.\\ | ||
+ | An electric motor is an electromechanical device which can turn electrical energy into mechanical energy. The motor turns because the electricity that flows in its winding generates a magnetic field that inducts the mechanical force between the winding and the magnet. Electric motors are made in many variants, of which the simplest is the permanent-magnet DC motor. | ||
+ | |||
+ | === DC Motor (One Direction) === | ||
+ | DC motor is a device which converts direct current into mechanical rotation. DC motor consists of permanent magnets in the stator and coils in the rotor. Applying the current to coils creates an electromagnetic field, and the rotor tries to align itself to the magnetic field. Each coil is connected to a commutator, which in turn supplies coils with current, thus ensuring continuous rotation. Some motors have a tachometer functionality as the loopback signal that generates a pulse train of frequency proportional to the rotation speed. Tacho signal can be connected to a digital or interrupt input of a microcontroller allowing for determining actual rotation speed. DC motors are widely used in power tools, toys, electric cars, robots, etc. | ||
+ | |||
+ | <figure label> | ||
+ | {{ : | ||
+ | < | ||
+ | </ | ||
+ | |||
+ | <figure label> | ||
+ | {{ : | ||
+ | < | ||
+ | </ | ||
+ | |||
+ | <code c> | ||
+ | void setup () | ||
+ | { | ||
+ | pinMode(5, | ||
+ | //The function for turning on the motor is defined | ||
+ | #define motON digitalWrite(5, | ||
+ | //The function for turning off the motor is defined | ||
+ | #define motOFF digitalWrite(5, | ||
+ | } | ||
+ | void loop () | ||
+ | { | ||
+ | motON; //Turn on the motor | ||
+ | } | ||
+ | |||
+ | </ | ||
+ | |||
+ | |||
+ | === DC Motor With H-Bridge === | ||
+ | |||
+ | The H-bridge has earned its name because of its resemblance to the capital ‘H’ wherein all the corners are switches, and the electric motor is in the middle. This bridge is usually used for operating permanent-magnet DC motors, electromagnets and other similar elements because it allows operating with significantly bigger current devices using a small current. | ||
+ | By switching the switches, it is possible to change the motor direction. It is important to remember that the switches must be turned on and off in pairs. | ||
+ | |||
+ | <figure label> | ||
+ | {{ : | ||
+ | < | ||
+ | </ | ||
+ | |||
+ | When all of the switches are turned off, the motor is in free movement. It is not always acceptable, so two solutions can be implemented. If both positive or negative switches are turned on at the top or at the bottom, then the motor coil is shorted, not allowing it to have a free rotation – it is slowed down faster. The fastest option to stop the motor is to turn the H-bridge in the opposite direction for some period of time. **Remember!** Neither of these braking mechanisms is good for the H-bridge or the power source because of excessive current appearance. That is why this action is unacceptable without a particular reason because it can damage the switches or the power source. The motor management can be reflected in the table. | ||
+ | |||
+ | <table label> | ||
+ | < | ||
+ | ^ Upper left ^ Upper right ^ Lower left ^ Lower right ^ Motor work mode ^ | ||
+ | | **On** | Off | Off | **On** | **Turns in one direction** | | ||
+ | | Off | **On** | **On** | Off | **Turns in another direction** | | ||
+ | | **On** | **On** | Off | Off | Braking | | ||
+ | | Off | Off | **On** | **On** | Braking | | ||
+ | </ | ||
+ | |||
+ | The complicated part is the realisation of switches, usually implemented as relays or appropriate power transistors. The biggest drawback of relays is that they can only turn the engine on or off. Transistors must be used if the rotation speed needs to be regulated using the pulse width modulation. The MOSFET-type transistors should be used to ensure a large amount of power. | ||
+ | Nowadays, the stable operation of the bridge is ensured by adding extra elements. All elements can be encapsulated in a single integrated circuit, e.g. L293D. | ||
+ | |||
+ | <figure label> | ||
+ | {{ : | ||
+ | < | ||
+ | </ | ||
+ | |||
+ | The L293D microchip consists of two H-bridges and is made for managing two motors. It has separate control pins for the left and right branches avoiding the power short circuit if connected properly. An example schematic diagram | ||
+ | of connecting the chip to the Arduino Uno board can be seen in the following figure. Notice that using a PWM signal allows to control the rotation speed. | ||
+ | |||
+ | <figure label> | ||
+ | {{ : | ||
+ | < | ||
+ | </ | ||
+ | |||
+ | The example code: | ||
+ | <code c> | ||
+ | int dirPin1 = 7; //1st direction pin | ||
+ | int dirPin2 = 8; //2nd direction pin | ||
+ | int speedPin = 5; //Pin responsible for the motor speed | ||
+ | |||
+ | void setup () | ||
+ | { | ||
+ | pinMode (dirPin1, | ||
+ | pinMode (dirPin2, | ||
+ | pinMode (speedPin, | ||
+ | } | ||
+ | |||
+ | void loop () | ||
+ | { | ||
+ | analogWrite(speedPin, | ||
+ | //Speed value can be from 0 to 255 | ||
+ | | ||
+ | int motDirection = 1; //Motor direction can be either 0 or 1 | ||
+ | | ||
+ | if (motDirection) //Setting motor direction | ||
+ | {//If 1 | ||
+ | digitalWrite(dirPin1, | ||
+ | digitalWrite(dirPin2, | ||
+ | } | ||
+ | else | ||
+ | {//If 0 | ||
+ | digitalWrite(dirPin1, | ||
+ | digitalWrite(dirPin2, | ||
+ | } | ||
+ | } | ||
+ | |||
+ | </ | ||
+ | |||
+ | == Linear actuator == | ||
+ | A bidirectional DC motor, usually controlled with an H-bridge and equipped with thread gear, can be used to implement the linear actuators.\\ | ||
+ | Linear actuators used to be equipped with end position detectors such as switches, or eventually, their end positions can be detected with overload detection. A simple linear actuator is present in figure {{ref> | ||
+ | <figure linactuator> | ||
+ | {{ : | ||
+ | < | ||
+ | </ | ||
+ | |||
+ | === Stepper Motor === | ||
+ | |||
+ | Stepper motors can be moved by a certain angle or step. The full rotation of the motor is divided into small, equal steps. Stepper motor has many individually controlled electromagnets; | ||
+ | An example of use can be found in the source ((https:// | ||
+ | |||
+ | <figure label> | ||
+ | {{ : | ||
+ | < | ||
+ | </ | ||
+ | |||
+ | <figure label> | ||
+ | {{ : | ||
+ | < | ||
+ | </ | ||
+ | |||
+ | The example code: | ||
+ | <code c> | ||
+ | #include < | ||
+ | |||
+ | int in1Pin = 12; //Defining stepper motor pins | ||
+ | int in2Pin = 11; | ||
+ | int in3Pin = 10; | ||
+ | int in4Pin = 9; | ||
+ | |||
+ | //Define a stepper motor object | ||
+ | Stepper motor(512, in1Pin, in2Pin, in3Pin, in4Pin); | ||
+ | |||
+ | void setup() | ||
+ | { | ||
+ | pinMode(in1Pin, | ||
+ | pinMode(in2Pin, | ||
+ | pinMode(in3Pin, | ||
+ | pinMode(in4Pin, | ||
+ | |||
+ | Serial.begin(9600); | ||
+ | motor.setSpeed(20); | ||
+ | } | ||
+ | |||
+ | void loop() | ||
+ | { | ||
+ | motor.step(5); | ||
+ | } | ||
+ | </ | ||
+ | |||
+ | === Servomotor === | ||
+ | |||
+ | The servomotor includes the internal closed-loop position feedback mechanism that precisely controls its position angle. To set the angle, the PWM technique is used. Additionally, | ||
+ | |||
+ | From the image {{ref> | ||
+ | The servomotor management chain meets the impulse every 20 ms, but the pulse width shows the position that the servomotor has to reach. For example, 1 ms corresponds to the 0° position but 2 ms – to the 180° position against the starting point. When entering the defined position, the servomotor will keep it and resist any outer forces that are trying to change the current position. The graphical representation is in the image {{ref> | ||
+ | |||
+ | <figure servomotor> | ||
+ | {{ : | ||
+ | < | ||
+ | </ | ||
+ | |||
+ | Just like other motors, servomotors have different parameters, where the most important one is the time of performance – the time that is necessary to change the position to the defined position. The best enthusiast-level servomotors do a 60° turn in 0.09 s. There are three types of servomotors: | ||
+ | * **positional rotation servomotor** – most widely used type of servomotor. With the help of a management signal, it can determine the position of the rotation angle from its starting position; | ||
+ | * **continuous rotation servomotor** – this type of motor allows setting the speed and direction of the rotation using the management signal. If the position is less than 90°, it turns in one direction, but if more than 90°, it turns in the opposite direction. The speed is determined by the difference in value from 90°; 0° or 180° will turn the motor at its maximum speed while 91° or 89° at its minimum rate; | ||
+ | * **linear servomotor** – with the help of additional transfers, it allows moving forward or backwards; it doesn’t rotate. | ||
+ | |||
+ | Unfortunately, | ||
+ | |||
+ | <figure label> | ||
+ | {{ : | ||
+ | < | ||
+ | </ | ||
+ | |||
+ | <figure label> | ||
+ | {{ : | ||
+ | < | ||
+ | </ | ||
+ | |||
+ | The example code: | ||
+ | <code c> | ||
+ | #include < | ||
+ | Servo servo; //Define a Servo object | ||
+ | |||
+ | void setup () | ||
+ | { | ||
+ | servo.attach(6); | ||
+ | servo.write(90); | ||
+ | Serial.begin(9600); | ||
+ | } | ||
+ | |||
+ | void loop () | ||
+ | { | ||
+ | servo.write(110); | ||
+ | delay(200); //wait for 200 ms | ||
+ | servo.write(70);// | ||
+ | delay(200); //Wait for 200 ms | ||
+ | } | ||
+ | |||
+ | </ | ||
+ | |||
+ | / | ||
+ | | ||
+ | / | ||
+ | | ||
+ | / | ||
+ | | ||
+ | / | ||
+ | | ||
+ | ===== ===== | ||
+ | <box # | ||
+ | <box # | ||
+ | ====== Notes for Further Studying ====== | ||
+ | <box # | ||
+ | <box # | ||
+ | |||
+ | It is worth nothing to mention that even every second, there grow new IoT ideas, hardware, software and applications. Because of that, technical, specific knowledge, mostly on hardware and software, becomes rapidly outdated. Moreover, due to the amount of information related to embedded systems development and IoT development, | ||
+ | |||
+ | The IOT-OPEN.EU project is instantly evolving and always brings new content, but it cannot be the only source of knowledge in the current stage of development. | ||
+ | We distribute all content via a single starting point, the website [[http:// | ||
+ | |||
+ | Please also note even if the IOT-OPEN.EU project is CC BY-NC licenced, resources juxtaposed below may need an access fee, registration and so on. | ||
+ | |||
+ | Many online platforms provide online courses by different universities about relevant topics like the Internet of Things, embedded systems, programming languages, connectivity and security, robotics, big data, computer vision and many more. Some of the most popular platforms are **Coursera** ((https:// | ||
+ | |||
+ | **Electronics Tutorials** website ((https:// | ||
+ | |||
+ | **Embedded Experts** website ((https:// | ||
+ | |||
+ | **Instructables** ((https:// | ||
+ | |||
+ | **Tinkercad** is a simple, online 3D design and 3D platform that also allows to model and test circuits ((https:// | ||
+ | |||
+ | **Wokwi** ((https:// | ||
+ | ======= Authors ======= | ||
+ | |||
+ | IOT-OPEN.EU Reloaded Consortium partners proudly present the 2nd edition of the Introduction to the IoT book. The complete list of contributors is juxtaposed below. | ||
+ | |||
+ | === ITT Group === | ||
+ | * Raivo Sell, Ph. D., ING-PAED IGIP | ||
+ | * Rim Puks, Eng. | ||
+ | * Mallor Kingsepp, Eng. | ||
+ | |||
+ | === Riga Technical University === | ||
+ | * Agris Nikitenko, Ph. D., Eng. | ||
+ | * Karlis Berkolds, M. sc., Eng. | ||
+ | * Anete Vagale, M. sc., Eng. | ||
+ | * Rudolfs Rumba, M. sc., Eng. | ||
+ | |||
+ | === Silesian University of Technology === | ||
+ | * Piotr Czekalski, Ph. D., Eng. | ||
+ | * Krzysztof Tokarz, Ph. D., Eng. | ||
+ | * Oleg Antemijczuk, | ||
+ | * Jarosław Paduch, M. sc., Eng. | ||
+ | * Godlove Suila Kuaban, M. sc., Eng. | ||
+ | |||
+ | === Tallinn University of Technology === | ||
+ | * Raivo Sell, Ph. D., ING-PAED IGIP | ||
+ | * Karl Läll, B. sc., Eng. | ||
+ | |||
+ | === SIA RobotNest === | ||
+ | * Karlis Berkolds, M. sc., Eng. | ||
+ | |||
+ | === IT Silesia === | ||
+ | * Łukasz Lipka, M. sc., Eng. | ||
+ | |||
+ | === University of Messina === | ||
+ | * Salvatore Distefano | ||
+ | * Rustem Dautov | ||
+ | * Riccardo Di Pietro | ||
+ | * Antonino Longo Minnolo | ||
+ | |||
+ | === ITMO University === | ||
+ | * Aleksandr Kapitonov, Ph. D., Assoc. Prof. | ||
+ | * Dmitrii Dobriborsci, | ||
+ | * Igor Pantiukhin, M. sc., Eng. | ||
+ | * Valerii Chernov, Eng. | ||
+ | |||
+ | ==== Graphic Design and Images ==== | ||
+ | * Blanka Czekalska, M. sc., Eng., Arch. | ||
+ | * Piotr Czekalski, Ph. D., Eng. | ||
+ | |||
+ | ==== Reviewers (1st edition) ==== | ||
+ | * Fabio Bonsignorio, | ||
+ | * Artur Pollak, M. sc., Eng. -- CEO at APAGroup | ||
+ | * Ivars Parkovs, M. sc., Eng. -- R&D Senior Engineer at "SAF Tehnika" | ||
+ | * Janis Lacaunieks, M. sc., Eng. -- R&D Engineer at "SAF Tehnika" | ||
+ | ====== Versions ====== | ||
+ | |||
+ | This page keeps track of the content reviews and versions done as a continuous maintenance process | ||
+ | |||
+ | < | ||
+ | < | ||
+ | ^ ^ Version | ||
+ | | 1 | v 0.1 | 01.05.2023 | ||
+ | | 2 | v 0.2 | 02.05.2023 | ||
+ | | 3 | v 0.25 | 08.05.2023 | ||
+ | | 4 | v 0.26 | 18.06.2023 | ||
+ | | 5 | v 0.27 | 28.06.2023 | ||
+ | | 6 | v 0.28 | 28.06.2023 | ||
+ | | 7 | v 0.29 | 28.06.2023 | ||
+ | | 8 | v.0.3 | 19.08.2023 | ||
+ | | 9 | v.0.31 | ||
+ | | 10 | v.0.32 | ||
+ | </ | ||
+ | ======= Preface ======= | ||
+ | This book and its offshoots were prepared to provide comprehensive information about the Internet of Things on the engineering level.\\ | ||
+ | Its goal is to introduce IoT to bachelor students, master students, technology enthusiasts and engineers willing to extend their current knowledge with the latest hardware and software achievements in the scope of the Internet of Things.\\ | ||
+ | This book is also designated for teachers and educators willing to prepare a course on IoT. | ||
+ | |||
+ | We (Authors) assume that persons willing to study this content possess some general knowledge about IT technology, i.e. understand what an embedded system is, know the general idea of programming (in C/C++) and are aware of wired and wireless networking as it exists nowadays. | ||
+ | |||
+ | This book constitutes a comprehensive manual for IoT technology; however, it is not a complete encyclopedia nor exhausts the market. The reason for it is pretty simple – IoT is so rapidly changing technology that new devices, ideas and implementations appear daily. Once you read this book, you can quickly move over the IoT environment and market, easily chasing ideas and implementing your IoT infrastructure. | ||
+ | |||
+ | We also believe this book will help adults that took their technical education some time ago to update their knowledge. | ||
+ | |||
+ | We hope this book will let you find brilliant ideas in your professional life, see a new hobby, or even start an innovative business. | ||
+ | |||
+ | ** Playing with real or virtual hardware and software is always fun, so keep going! ** | ||
+ | ======= Project Information ======= | ||
+ | ThisBook was implemented under the Erasmus+ KA2 projects: | ||
+ | * Strategic Partnerships in the Field of Education, Training, and Youth – Higher Education, 2016, IOT-OPEN.EU – Innovative Open Education on IoT: Improving Higher Education for European Digital Global Competitiveness, | ||
+ | * Cooperation Partnerships in higher education, 2022, IOT-OPEN.EU Reloaded: Education-based strengthening of the European universities, | ||
+ | |||
+ | **Erasmus+ Disclaimer**\\ | ||
+ | This project has been funded with support from the European Commission. \\ | ||
+ | This publication reflects the views only of the author, and the Commission cannot be held responsible for any use which may be made of the information contained therein. | ||
+ | |||
+ | **Copyright Notice**\\ | ||
+ | This content was created by the IOT-OPEN.EU Consortium: 2016–2019 and IOT-OPEN.EU Reloaded Consortium 2022-2025.\\ | ||
+ | The content is Copyrighted and distributed under CC BY-NC [[https:// | ||
+ | <figure label> | ||
+ | {{en: | ||
+ | </ | ||
+ | In case of commercial use, please contact IOT-OPEN.EU Reloaded Consortium representative. | ||
+ | <box # | ||
+ | <box # | ||
+ | ====== Introduction ====== | ||
+ | <box # | ||
+ | <box # | ||
+ | |||
+ | Here comes the Internet of Things. | ||
+ | The name that recently makes red-hot people in business, researchers, | ||
+ | The name that non-technology related people consider a kind of magic and even a danger to their privacy. | ||
+ | The EU set the name as one of the emerging technologies and estimated the worldwide market will hit well over 500 billion US dollars in 2022, while the number of IoT devices in 2030 is expected to be over 3.2 billion. | ||
+ | |||
+ | What is IoT (Internet of Things), then? | ||
+ | Surprisingly, | ||
+ | |||
+ | |||
+ | |||
+ | ==== Color coding ==== | ||
+ | |||
+ | To simplify the selection of different topics, a simple colour coding was introduced, indicating the skills required to cover particular topics. Colour codes are organized in the form of colour bars enclosing chapter titles. | ||
+ | |||
+ | Explanation: | ||
+ | |||
+ | === === | ||
+ | |||
+ | <box # | ||
+ | <box # | ||
+ | === This chapter is for beginners (including amateurs) or higher === | ||
+ | <box # | ||
+ | <box # | ||
+ | |||
+ | <box # | ||
+ | |||
+ | <box # | ||
+ | <box # | ||
+ | === This chapter is for bachelor students of higher === | ||
+ | <box # | ||
+ | <box # | ||
+ | |||
+ | <box # | ||
+ | |||
+ | <box # | ||
+ | <box # | ||
+ | === This chapter is for master students of higher === | ||
+ | <box # | ||
+ | <box # | ||
+ | |||
+ | |||
+ | ===== ===== | ||
+ | <box # | ||
+ | <box # | ||
+ | ===== Definition of IoT ===== | ||
+ | <box # | ||
+ | <box # | ||
+ | Let us roll back to the 1970s first. | ||
+ | In 1973 the first RFID device was patented. This device was the key enabling technology even if it does not look nor remind modern IoT devices. The low power (actually here passive) solution with a remote antenna large enough to collect energy from the electromagnetic field and power the device brought an idea of uniquely identifiable items. That somehow mimics well-known EAN barcodes and the evolution used nowadays, like QR codes, but every single thing has a different identity here. In contrast, EAN barcodes present a class of products, not an individual one. The possibility to identify a unique identity remotely became fundamental to the IoT as it's known today. RFID is not the only technology standing behind IoT. In the 1990s, the rapid expansion of wireless networks, including broadband solutions like cellular-based data transfers with their consequent generations, | ||
+ | |||
+ | ==== What is IoT? ==== | ||
+ | The phrase " | ||
+ | International Telecommunication Union (ITU) in the ITU Internet report in 2005 (("ITU Internet Reports 2005: The Internet of Things." | ||
+ | The understanding and definitions of IoT changed over the years, but now all agree that this cannot be seen as a technology issue only. | ||
+ | According to IEEE " | ||
+ | ^IEEE Definition of IoT^ | ||
+ | |A network of items – each embedded with sensors – connected to the Internet.| | ||
+ | It relates to the physical aspects of IoT only. The Internet of Things also addresses other aspects that cover many areas ((" | ||
+ | *enabling technologies, | ||
+ | *software, | ||
+ | *applications and services, | ||
+ | *business models, | ||
+ | *social impact, | ||
+ | *security and privacy aspects. | ||
+ | IEEE, as one of the most prominent standardisation organisations, | ||
+ | It is essential to understand that IoT systems are not only small, local-range systems. ITU-T has defined IoT as: | ||
+ | ^ITU-T Definition of IoT^ | ||
+ | |A global infrastructure for the information society, enabling advanced services by interconnecting (physical and virtual) things based on existing and evolving interoperable information and communication technologies.| | ||
+ | In the book ((Ovidiu Vermesan, Peter Friess (eds.): Digitising the Industry, Internet of Things Connecting the Physical, Digital and Virtual Worlds, River Publishers Series in Communications, | ||
+ | IoT impacts many areas of human activity: manufacturing, | ||
+ | In this course, we will consider the technical aspects mainly. | ||
+ | ==== " | ||
+ | In the IoT world, the " | ||
+ | " | ||
+ | ^CERP-IoT Definition of " | ||
+ | |A real/ | ||
+ | It is quite easy to find other terms used in the literature like "smart object", | ||
+ | ===Passive Thing=== | ||
+ | One can imagine that almost everything in our surroundings is tagged with an RFID element. They do not need a power supply; they respond with a short message, usually containing the identification number. Modern RFID can achieve 6 to 7 meters of the range. Using the active RFID reader, we can quickly locate lost keys and know if we still have the butter in the fridge and in which wardrobe there is our favourite t-shirt. | ||
+ | ===Active Thing=== | ||
+ | If the " | ||
+ | Active things can also receive control signals from the central controller to control the environment: | ||
+ | ===Autonomous Thing=== | ||
+ | This thing does not even require the controller to realise the proper decision. An autonomous vacuum cleaner can clean our house when it detects that we aren't home and the floor needs cleaning. The fridge can order our favourite beverage once the last bottle is almost empty. | ||
+ | ====Sensor Network==== | ||
+ | Sensor Networks are a subset of the IoT devices used as a collaborative solution to grab data and send it for further processing. Opposite to the general IoT devices, Sensor Network devices do not have any actuators that can apply an action to the external world. The data flow is unidirectional, | ||
+ | ====IoT vs Embedded Systems==== | ||
+ | IoT systems and embedded systems share almost the same domain. They frequently use the same microcontrollers, | ||
+ | ===== ===== | ||
+ | <box # | ||
+ | <box # | ||
+ | =====Enabling Technologies===== | ||
+ | <box # | ||
+ | <box # | ||
+ | In this chapter, there is an approach to describe modern technologies that appeared in the last few years, enabling the idea of IoT to be widely implementable. In the ((Ovidiu Vermesan, Peter Friess (eds.): Digitising the Industry, Internet of Things Connecting the Physical, Digital and Virtual Worlds, River Publishers Series in Communications, | ||
+ | Similar analysis has been done in ((Ala Al-Fuqaha, Mohsen Guizani, Mehdi Mohammadi, Mohammed Aledhari, Moussa Ayyash: Internet of Things: A Survey on Enabling Technologies, | ||
+ | ====Edge class devices==== | ||
+ | In recent years one can observe rapid growth in the field of microprocessors. It includes not only the powerful desktop processors but also microcontrollers – elements that are used in small-scale embedded systems. We can also notice the popularity of microprocessor systems that can be easily integrated with other factors, like sensors, and actuators, connected to the network. Essential is also the availability of programming tools and environments supported by different companies and communities. An excellent example of such a system is Arduino. Those devices are low-power, constrained devices, usually battery-powered and, in most cases, communicating wirelessly. | ||
+ | ====Fog class devices==== | ||
+ | The same growth can be observed in the advanced constructions comparable to low-end computers. They have more powerful processors, memory and networking connectivity built-in than small-scale computer systems. They can work under the control of multitasking operating systems like Linux and Windows and embedded or real-time operating systems like FreeRTOS. Having many libraries, they can successfully work as hubs for local storage, local controllers and gateways to the Internet. Raspberry Pi and the nVidia Jetson series are examples of such systems. This category of devices frequently contains hardware accelerated (such as GPU) AI-capable solutions, i.e. nVidia Jetson Nano or Xavier series. Those devices can be battery or mains powered. Often, they are green energy powered: i.e. with a larger backup battery and energy harvesting solution (such as solar panel). | ||
+ | ====Access to the Internet==== | ||
+ | Nowadays, the Internet is (almost) everywhere. There are lots of wireless networks available in private and public places. The price of cellular access (3G/4G/5G) is low, offering a suitable data transfer performance. Connecting the " | ||
+ | ====IP Addressing Evolution==== | ||
+ | The primary paradigm of IoT is that every unit can be individually addressed. With the addressing scheme used in IPv4, it wouldn' | ||
+ | ====Data Storage and Processing==== | ||
+ | IoT devices generate the data to be stored and processed somewhere. If there is a couple of sensors, the amount of data is not very big, but if there are thousands of sensors generating data hundreds of times every second. The cloud can handle it – the massive place for the data with tools and applications ready to help with data processing. Some big, global clouds are available for rent, offering not only storage but also Business Intelligence tools, Artificial Intelligence analytic algorithms. There are also smaller private clouds created to cover the needs of one company only. Many universities have their own High-Performance Computing Centre. | ||
+ | ====Mobile Devices==== | ||
+ | Many people want to be connected to the global network everywhere, anytime, having their " | ||
+ | |||
+ | The technologies we mentioned here are the most recognisable. Still, there are many others, more minor, described only in the technical language in some standard description document, hidden under the colourful displays between large data centres, making our IoT world operable. In this book, we will describe some of them. | ||
+ | |||
+ | ====A special note on Fog class and Edge class devices==== | ||
+ | Technology development instantly shifts devices between categories. A border between Fog and Edge class devices is conventional; | ||
+ | <box # | ||
+ | <box # | ||
+ | ===== Mobility – New Paradigm for IoT Systems ===== | ||
+ | <box # | ||
+ | <box # | ||
+ | |||
+ | |||
+ | IoT has already been defined as a network of physical things or devices that might include sensors or simple data processing units, complex actuators, and significant hybrid computing power. Today IoT systems have transitioned from being perceived as sensor networks to smart-networked systems capable of solving complex tasks in mass production, public safety, logistics, medicine and other domains, requiring a broader understanding and acceptance of current technological advancements, | ||
+ | |||
+ | Since the very beginning of sensor networks, one of the main challenges has been data transport and data processing, where significant efforts have been put by the ICT community towards service-based system architectures. However, The current trend already provides considerable computing power even in small mobile devices. Therefore, the concepts of future IoT already shifted towards smarter and more accessible IoT devices, and data processing has become possible closer to the Fog and Edge. | ||
+ | |||
+ | ==== Cloud Computing ==== | ||
+ | |||
+ | Cloud-based computing is a relatively well-known and adequately employed paradigm where IoT devices can interact with remotely shared resources such as data storage, | ||
+ | data processing, data mining and other services are unavailable to them locally because of the constrained hardware resources (CPU, ROM, RAM) or energy consumption limits. | ||
+ | Although the cloud computing paradigm can handle vast amounts of data from IoT clusters, the transfer of extensive data to and from cloud computers presents a challenge due to limited bandwidth((Arslan Munir, IFCIoT: Integrated Fog Cloud IoT Architectural Paradigm for the Future Internet of Things, IEEE Consumer Electronics Magazine, Vol. 6, Issue 3, July 2017 )). | ||
+ | Consequently, | ||
+ | |||
+ | ==== Fog Computing ==== | ||
+ | |||
+ | Fog computing addressed the bottlenecks of cloud computing regarding data transport while providing the needed services to IoT systems. | ||
+ | It is a new trend in computing that aims to process the data near the data source. Fog computing pushes applications, | ||
+ | Fog computing enables data analytics and knowledge generation at the data source. Furthermore, | ||
+ | The recent development of energy-efficient hardware with AI acceleration enters the fog class of the devices, putting Fog Computing in the middle of the interest of IoT application development and extending new horizons to them. Fog Computing is more energy efficient than raw data transfer to the cloud and back, and in the current scale of the IoT devices, the application is meant for the future of the planet Earth. Fog Computing usually also brings a positive impact on IoT security, i.e. sending to the cloud preprocessed and depersonalised data and providing distributed computing capabilities that are more attack resistant. | ||
+ | |||
+ | ==== Edge Computing ==== | ||
+ | Recent development in hardware, power efficiency and a better understanding of the IoT data nature, including such aspects as, i.e. privacy and security, led to solutions where data is being processed and preprocessed right to their source in the Edge class devices. Edge data processing on end-node IoT devices is crucial in systems where privacy is essential and sensitive data is not to be sent over the network (i.e. biometric data in a raw form). Moreover, distributed data processing can be considered more energy efficient in some scenarios where, i.e. extensive, power-consuming processing can be performed during green energy availability. | ||
+ | |||
+ | ==== Cognitive IoT Systems ==== | ||
+ | |||
+ | According to ((S.Matthews at http:// | ||
+ | * **understanding** – in the case of IoT, it means systems' | ||
+ | * **reasoning** – involves decision-making according to the understood model and acquired data; | ||
+ | * **learning** – creating new knowledge from the existing, sensed data and elaborated models. | ||
+ | Usually, cognitive IoT systems or C-IoT are expected to add more resilience to the solution. Resilience is a complex term and is differently explained under different contexts; however, there are standard features for all resilient systems. As a part of their resilience, C-IoT should be capable of self-failure detection and self-healing that minimises or gradually degrades the system' | ||
+ | Recent development in the Fog and Edge class devices and the efficient software leverage cognitive IoT Systems to a new level. | ||
+ | |||
+ | All three approaches, from cloud to cognitive systems, focus on adding value to IoT devices, system users and related systems on-demand. | ||
+ | Since market and technology acceptance of mobile devices is still growing, and the amount of produced data from those devices is growing exponentially, | ||
+ | driving forces of the technological advancements of the near future. | ||
+ | ===== ===== | ||
+ | <box # | ||
+ | <box # | ||
+ | ====== Notes for Further Studying ====== | ||
+ | <box # | ||
+ | <box # | ||
+ | |||
+ | It is worth nothing to mention that even every second, there grow new IoT ideas, hardware, software and applications. Because of that, technical, specific knowledge, mostly on hardware and software, becomes rapidly outdated. Moreover, due to the amount of information related to embedded systems development and IoT development, | ||
+ | |||
+ | The IOT-OPEN.EU project is instantly evolving and always brings new content, but it cannot be the only source of knowledge in the current stage of development. | ||
+ | We distribute all content via a single starting point, the website [[http:// | ||
+ | |||
+ | Please also note even if the IOT-OPEN.EU project is CC BY-NC licenced, resources juxtaposed below may need an access fee, registration and so on. | ||
+ | |||
+ | Many online platforms provide online courses by different universities about relevant topics like the Internet of Things, embedded systems, programming languages, connectivity and security, robotics, big data, computer vision and many more. Some of the most popular platforms are **Coursera** ((https:// | ||
+ | |||
+ | **Electronics Tutorials** website ((https:// | ||
+ | |||
+ | **Embedded Experts** website ((https:// | ||
+ | |||
+ | **Instructables** ((https:// | ||
+ | |||
+ | **Tinkercad** is a simple, online 3D design and 3D platform that also allows to model and test circuits ((https:// | ||
+ | |||
+ | **Wokwi** ((https:// | ||
+ | ===== ===== | ||
+ | <box # | ||
+ | <box # | ||
+ | ===== Data Management Aspects in IoT ===== | ||
+ | <box # | ||
+ | <box # | ||
+ | |||
+ | Data management is a critical task in IoT. | ||
+ | Due to the high number of devices (things) already available, that is tens of billions, and considering the data traffic generated by each of them through, i.e. sensor networks, infotainment (soft news) or surveillance systems, mobile social network clients, and so on, we are now even beyond the ZettaByte (ZB 2^70, 10^21 bytes) era. | ||
+ | This opened up several new challenges in (IoT) data management, giving rise to data sciences and big data technologies. | ||
+ | Such challenges have not to be considered as main issues to solve but also as significant opportunities fuelling the digital economy with new directions such as Cloudonomics (([[http:// | ||
+ | Therefore, properly managing data in IoT contexts is not only critical but also of strategic importance for business players as well as for users, evolving into **prosumers** (producers-consumers). | ||
+ | |||
+ | From a technological perspective, | ||
+ | |||
+ | * **data source**: data generation and production is a relevant part of IoT, involving sensors probing the physical system. In a cyber-physical-social system view, such sensors could be virtual (e.g. software) or even human (e.g. citizens, crowdsensing). The main issues in data production are related to the type and format of data, heterogeneity in measurements and similar issues. Semantics is the key to solving these issues, also through specific standards such as Sensor Web Enablement and Semantic Sensor Network; | ||
+ | * **data collection/ | ||
+ | * **filtering**: | ||
+ | * **aggregation/ | ||
+ | * **processing**: | ||
+ | * **storage/ | ||
+ | * **delivering/ | ||
+ | * **security and privacy**: data privacy and security are among the most critical issues in IoT data management. Good results and reliable techniques for secure data transmission, | ||
+ | ===== ===== | ||
+ | <box # | ||
+ | <box # | ||
+ | ===== IoT Application Domains ===== | ||
+ | <box # | ||
+ | <box # | ||
+ | |||
+ | Application domains of the Internet of Things solutions are vast. Most prominent applications include (among others) ((https:// | ||
+ | * building and home automation, | ||
+ | * smart water, | ||
+ | * internet of food, | ||
+ | * smart metering, | ||
+ | * smart city (including logistics, retail, transportation), | ||
+ | * industrial IoT, | ||
+ | * precision agriculture and smart farming, | ||
+ | * security and emergencies, | ||
+ | * healthcare and wellness (including wearables), | ||
+ | * smart environment, | ||
+ | * energy management, | ||
+ | * robotics, | ||
+ | * smart grids. | ||
+ | |||
+ | **Smart Homes** are one of the first examples that come to mind when discussing Internet of Things domain applications. Smart home benefits include reduced energy wastage, the quality and reliability of devices, system security, reduced cost of basic needs, etc. Some home automation examples are environmental control systems that monitor and control heating, ventilation, | ||
+ | |||
+ | In **Smart City**, multiple IoT-based services are applied to different areas of urban settings. The aim of the smart city is the best use of public resources, improvement of the quality of resources provided to people and reduction of operating costs of public administration ((https:// | ||
+ | |||
+ | **Smart Grid** is a digital power distribution system. This system gathers information using smart meters, sensors and other devices. After these data are processed, power distribution can be adapted accordingly. Smart grids deliver sustainable, | ||
+ | |||
+ | In **Precision Agriculture** and **Smart Farming** IoT solutions can be used to monitor the moisture of the soil and conditions of the plants, control microclimate conditions and monitor the weather conditions to improve farming ((https:// | ||
+ | |||
+ | **Internet of Food** integrates many of the aforementioned techniques and encompasses different stages of the food delivery chain, including smart farming, food processing, transportation, | ||
+ | |||
+ | Similar to precision agriculture, | ||
+ | |||
+ | **Industrial IoT** and **smart factories** are part of the Industry 4.0 revolution. In this model, modern factories can automate complex manufacturing tasks, thanks to the Machine-To-Machine communication model, which provides more flexibility in the manufacturing process to enable personalised, | ||
+ | |||
+ | In the **healthcare and wellness**, IoT applications can monitor and diagnose patients and manage people and medical resources. It allows remote and continuous monitor the vital signs of patients to improve medical care and wellness of patients ((https:// | ||
+ | |||
+ | **Wearables** used in IoT applications should be highly energy efficient, ultra-low power and small-sized. Wearables are installed with sensors and software for data and information collected about the user. | ||
+ | Devices used in daily life like Fitbit ((https:// | ||
+ | ====== IoT Hardware Overview ====== | ||
+ | IoT hardware infrastructure is mostly inheriting from the embedded systems of the SoC type. As IoT devices are by its nature network-enabled, | ||
+ | |||
+ | * "4.1. Most Noticeable Platforms"; | ||
+ | |||
+ | * "4.2. [[en: | ||
+ | | ||
+ | * "4.3. [[en: | ||
+ | |||
+ | * "4.4. [[en: | ||
+ | |||
+ | * "4.5. [[en: | ||
+ | |||
+ | ===== Most Noticeable Platforms ===== | ||
+ | IoT market is an emerging one. New hardware solutions appear almost daily, while others disappear quick. At the moment of writing this publication (2016–2019), | ||
+ | * AVR: Arduino – a development board that uses Atmel SoC, that is no doubt the most popular development platform for enthusiasts and professionals. Arduino itself barely offers networking capabilities yet; there is a vast number of extension boards including network interfaces (both wired and wireless); | ||
+ | * ESP: Espriff (Espressif Systems) – the great SoC solution of the single SoC including wireless network interfaces; | ||
+ | * ARM: Raspberry Pi (and its clones) – advanced boards, including Linux operating system with GUI interface, even able to replace desktop computers. | ||
+ | |||
+ | |||
+ | ===== ===== | ||
+ | <box # | ||
+ | <box # | ||
+ | ===== Embedded Systems Communication Protocols ===== | ||
+ | <box # | ||
+ | <box # | ||
+ | |||
+ | Understanding the principals of communication are essential for further reading on hardware and programming. Most microcontrollers (including SoCs) can communicate in the protocols juxtaposed below right "out of the box". Interfaces can be implemented in hardware or (recently) in software. Some microcontrollers may require an external, dedicated protocol converter (a chip or a module). | ||
+ | |||
+ | IoT systems are typically structured into three basic layers ((Internet of Things: Security Vulnerabilities and Challenges Ioannis Andrea, Chrysostomos Chrysostomou, | ||
+ | The function of the perception layer is to keep contact with the physical environment. Devices working in this layer are designed as embedded systems. They include the microprocessor or microcontroller, | ||
+ | Sensors are elements that convert a value of some physical parameter into an electrical signal, while actuators are elements that control environment parameters. | ||
+ | Sensors and actuators are interfaced with the microcontroller using different connection types. This chapter describes some internal protocols used to communicate between microcontrollers and other electronic elements that can be named “embedded protocols”. Description of the protocols used for wire and wireless transmission between the perception layer and higher layers is present in [[en: | ||
+ | The embedded protocol that can be used in specific implementation depends mainly on the type of the peripheral element. Some of them use an analogue signal that the microcontroller must convert to digital internally, some directly implement digital communication protocol. | ||
+ | |||
+ | ====Analog==== | ||
+ | Simple sensors do not implement the conversion and communication logic, and the output is just the analogue signal – voltage level depending on the value of the parameter that is measured. It needs to be further converted into a digital representation; | ||
+ | Examples of the sensors with analogue output are a photoresistor, | ||
+ | |||
+ | ====Digital==== | ||
+ | Dummy, true/false information can be processed via digital I/O. Most devices use positive logic, where, i.e. +5 V (TTL) or +3.3 V (those are the most popular, yet there do exist other voltage standards) presents a logical one, while 0V presents logical zero. In real systems this bounding is fuzzy and brings some tolerance, simplifying, | ||
+ | |||
+ | ====SPI==== | ||
+ | One of the most popular interfaces to connect the sensor is SPI (Serial Peripheral Interface). It is a synchronous serial interface and protocol that can transmit data with speed up to 20 Mbps. SPI is used to communicate microcontrollers with one or more peripheral devices over short distances – usually internally in the device. In SPI connection there is always one master device, in most cases the microcontroller (μC) that controls the transmission, | ||
+ | <table Ref.Tab.1> | ||
+ | < | ||
+ | ^ <fs xx-small> | ||
+ | | <fs xx-small> | ||
+ | | <fs xx-small> | ||
+ | | <fs xx-small> | ||
+ | | <fs xx-small> | ||
+ | </ | ||
+ | MISO is intended to send bits from slave to master, MOSI transmits data from master to slave. SCK line is used for sending clock pulses which synchronize data transmission. The clock signal is always generated by the master device. | ||
+ | Every SPI compatible device has the SS (Slave Select) input that enables communication in this specific device. Master is responsible to generate this enable signal – separately for every slave in the system. | ||
+ | <figure Ref.Pic.1> | ||
+ | {{ : | ||
+ | < | ||
+ | </ | ||
+ | |||
+ | SPI is used in many electronic elements like analogue to digital converters (ADC), real-time clocks (RTC), EEPROMs, LCD displays, communication interfaces (e.g. Ethernet, WiFi) and many others. | ||
+ | Due to different hardware implementations, | ||
+ | <table Ref.Tab.2> | ||
+ | < | ||
+ | ^ <fs xx-small> | ||
+ | | <fs xx-small> | ||
+ | | <fs xx-small> | ||
+ | | <fs xx-small> | ||
+ | | <fs xx-small> | ||
+ | </ | ||
+ | |||
+ | It results in different timings of the clock signal concerning the data sent. Clock polarity = 0 means that the idle state of the SCK is 0, so every data bit is synchronised with the pulse of logic 1. Clock polarity = 1 reverses these states. Output edge (rising/ | ||
+ | ====TWI (I2C)==== | ||
+ | TWI (Two Wire Interface) is one of the most popular communication protocol used in embedded systems. It has been designed by Philips as I2C (Inter-Integrated Circuit) for using in the audio-video appliances controlled by the microprocessor. There are many chips that can be connected to the processor with this interface, including: | ||
+ | * | ||
+ | * RAM memory chips, | ||
+ | * AD/DA converters, | ||
+ | * | ||
+ | * | ||
+ | * port extenders, | ||
+ | * | ||
+ | * specialised AV circuits. | ||
+ | TWI, as the name says, uses two wires for communication. One is the data line (SDA); the second is the clock line (SCL). Both lines are common to all circuits connected to the one TWI bus. The method of the communication of TWI is the master-slave synchronous serial transmission. It means that data is sent bit after bit synchronised with the clock signal. SCL line is always controlled by the master unit (usually the processor), the signal on the SDA line is generated by the master or one of the slaves – depending on the direction of communication. The frequency rate of the communication is up to 100 kHz for most of the chips, for some can be higher – up to 400 kHz. The new implementation allows even higher frequency rate is reaching 5 MHz. | ||
+ | At the output side of units, the lines have the open-collector or open-drain circuit. It means that there are external pull-up resistors needed to ensure proper operation of the TWI bus. Value of these resistors depends on the number of connected elements, speed of transmission and the power supply voltage and can be calculated with the formulas presented in Texas Instrument Application Report ((Rajan Arora, I2C Bus Pullup Resistor Calculation, | ||
+ | |||
+ | <figure Ref.Pic.2> | ||
+ | {{ : | ||
+ | < | ||
+ | </ | ||
+ | |||
+ | The data is sent using frames of bytes. Every frame begins with the sequence of signals that is called the start condition. This sequence is detected by slaves and causes them to collect the next eight bits that form the address byte – unique for every circuit on the bus. If one of the slaves recognises its address remains active until the end of the communication frame, others become inactive. To inform the master that some unit has been appropriately addressed slave responses with the acknowledge bit – it generates one bit of low level on the SDA line (the master generates clock pulse). After sending the proper address, data bytes are sent. The direction of the data bytes is controlled by the last bit of the address, for 0 data is transmitted by the master (Write), for 1 data is sent by the slave (Read). The receiving unit must acknowledge every full byte (eight bits). There is no limitation on the number of data bytes in the frame, for example, samples from the AD converter can be read byte continuously after byte. At the end of the frame, another special sequence is sent by the master – stop condition. It is also possible to generate another start condition without the stop condition. It is called a repeated start condition. | ||
+ | |||
+ | <figure Ref.Pic.3> | ||
+ | {{ : | ||
+ | < | ||
+ | </ | ||
+ | |||
+ | Address byte activates one chip on the bus only, so every unit must have a unique physical address. This byte usually consists of three elements: 4-bit field fixed by the producer, 3-bit field that can be set by connecting three pins of the chip to 0 (ground) or 1 (positive supply line), 1-bit field for setting the direction of communication (R/#W). Some elements (e.g. EEPROM memory chips) uses the 3-bit field for internal addressing so there can be only one such circuit connected to one bus. | ||
+ | There are no special rules for the data bytes. First data byte sent by the master can be used for configuration of the slave chip. In memory units, it is used for setting the internal address of the memory for writing or reading, in multi-channel AD converters to choose the analogue input. The detailed information on the meaning of every bit of the transmission is present in the documentation of the specific integrated circuit. | ||
+ | The I2C standard also defines the multi-master mode, but in most of the small projects, there is one master device only. | ||
+ | |||
+ | |||
+ | ====1-Wire==== | ||
+ | 1-Wire is a master-slave communication bus system designed formerly by Dallas Semiconductor Corp((https:// | ||
+ | Each 1-Wire device must contain logic unit to operate on the bus. The 1-Wire products include temperature, | ||
+ | |||
+ | ===1-Wire Protocol Description=== | ||
+ | Within the MicroLAN, there is always one master device, which may be a PC or a microcontroller unit. The master always initiates activity on the bus to avoid collisions on the network chain. If a collision occurs, the master device retries the communication. In the 1-Wire network, many devices can share the same bus line. To identify devices in the MicroLAN, each connected device has a unique 64-bit ID number. The least significant byte of the ID number defines the type of the device (temperature, | ||
+ | The 1-Wire protocol description contains several broadcast commands and commands used to address the selected device. The master sends a selection command, then the address of a slave selected device. This way, the next command is executed only by the addressed device. The 1-Wire bus implements enumeration procedure which allows the master to get information about ID numbers of all connected slave devices to the MicroLAN network. Device address includes the device type, and a CRC allows to identify what type of slaves are currently connected to the network chain for inventory purposes. The 64-bit address space is searched as a binary tree. It allows to find up to 75 devices per second. | ||
+ | |||
+ | The physical implementation of the 1-Wire network is based on an open drain master device connected to one or more open drain slaves. One single pull-up resistor for all devices pull the bus up to 3/5 V and can be used to power the slave devices. 1-Wire communication starts when a master or slave sets the bus to low voltage (connects the pull-up resistor to ground through its output MOSFET). Typical data speed of the 1-Wire interface is about 16.3 kbit/ | ||
+ | |||
+ | 1-Wire protocol allows for bursting the communication speed up by 10 factor. In this case, the master starts a transmission with a reset pulse pulling down the data line to 0 volts for at least 480 µs. It resets all slave devices in the network chain bus. Then, any slave device shows that it exists generating the " | ||
+ | |||
+ | To find the devices, the enumeration broadcast command must be sent by a master. The slave device response with all ID bits to the master and at the end it returns a 0. | ||
+ | |||
+ | <figure label> | ||
+ | {{ en: | ||
+ | < | ||
+ | </ | ||
+ | |||
+ | <figure label> | ||
+ | {{ en: | ||
+ | < | ||
+ | </ | ||
+ | |||
+ | <figure label> | ||
+ | {{ en: | ||
+ | < | ||
+ | </ | ||
+ | |||
+ | ===USB to 1-Wire Master=== | ||
+ | The DS9490B is a USB bridge and holder for a single F5-size iButton. The DS9490R is a USB bridge with 1-Wire RJ11 interface to accommodate 1-Wire receptacles and networks. | ||
+ | <figure label> | ||
+ | {{ : | ||
+ | </ | ||
+ | The bridge is based on the DS2490 chip developed by Dallas company, which allows to interconnect USB interface with 1-Wire bus. This required programming and electrical conversion between two different protocols in bidirectional way. The electrical wiring are present on Figure 9. | ||
+ | <figure label> | ||
+ | {{ : | ||
+ | </ | ||
+ | The appropriate 1-Wire cable pinout uses RJ11 telephone connectors. | ||
+ | <figure label> | ||
+ | {{ : | ||
+ | < | ||
+ | </ | ||
+ | |||
+ | |||
+ | ===1-Wire Products=== | ||
+ | The list of Dallas/ | ||
+ | * | ||
+ | * | ||
+ | * | ||
+ | * data loggers, | ||
+ | * | ||
+ | * | ||
+ | * | ||
+ | * | ||
+ | ===== ====== | ||
+ | <box # | ||
+ | <box # | ||
+ | ===== Arduino Overview ====== | ||
+ | <box # | ||
+ | <box # | ||
+ | |||
+ | No doubt, Arduino became the most widespread SoC, particularly among enthusiasts, | ||
+ | |||
+ | Using cheap Atmel AVR microcontrollers, | ||
+ | |||
+ | The beginnings of the Arduino are dated to the year 2003 in Italy. Their most popular development board was delivered to the market in the fall of 2010. While AVRs microcontrollers are considered to be embedded systems more than IoT, and most of the early Arduino boards didn't offer any network interface, even then, it is essential to understand the idea of how to work with SoCs, so we start our guide here. However, many extension boards are present, suitable for the standard development boards (so-called shields) that offer wired and wireless networking for Arduino. Some of the Arduino development boards nowadays do integrate networking SoC into one board, i.e. Arduino Yun. Also, their clones, mostly made by Chinese manufacturers, | ||
+ | |||
+ | The following chapters present the Arduino hardware overview, peripherals and programming as universal basics for IoT systems development using advanced processors like ESP: | ||
+ | |||
+ | * " | ||
+ | |||
+ | * " | ||
+ | |||
+ | * " | ||
+ | |||
+ | * " | ||
+ | |||
+ | * " | ||
+ | |||
+ | * " | ||
+ | |||
+ | * " | ||
+ | ==== ==== | ||
+ | <box # | ||
+ | <box # | ||
+ | ==== Overview of the Hardware Device Used ==== | ||
+ | <box # | ||
+ | <box # | ||
+ | |||
+ | === What is Arduino and Why to Use It? === | ||
+ | |||
+ | Arduino is an open-source platform based on easy-to-use hardware and software ((https:// | ||
+ | |||
+ | The Arduino board works by reacting on **inputs** that are received from various sensors and, after executing a **set of instructions**, | ||
+ | |||
+ | Arduino microcontrollers can be used both in research and everyday applications. It is easy to use for people with different backgrounds, | ||
+ | |||
+ | === The Most Common Arduino Boards === | ||
+ | |||
+ | Arduino boards can be divided into six sections depending on their specifications – entry level, enhanced features, Internet of things, education, wearable, and 3D printing boards. | ||
+ | |||
+ | The most common boards of Arduino are **Uno**, **Leonardo**, | ||
+ | |||
+ | |||
+ | <figure label> | ||
+ | {{ : | ||
+ | < | ||
+ | </ | ||
+ | |||
+ | ==== Digital Input/ | ||
+ | |||
+ | Digital input/ | ||
+ | |||
+ | <table Digital.I/ | ||
+ | < | ||
+ | ^ ^ <fs xx-small> | ||
+ | |<fs xx-small> | ||
+ | </ | ||
+ | |||
+ | ==== Pulse Width Modulation ==== | ||
+ | |||
+ | Pulse Width Modulation (PWM) is a function of a pin to generate a square wave signal, with a variable length of the HIGH level of the output signal. The PWM is used for digital pins to simulate the analogue output. | ||
+ | |||
+ | <table PWM> | ||
+ | < | ||
+ | ^ ^ <fs xx-small> | ||
+ | | <fs xx-small> | ||
+ | </ | ||
+ | |||
+ | ==== Analog Pins ==== | ||
+ | |||
+ | Analog pins convert the analogue input value to a 10-bit number, using Analog Digital Converter (ADC). This function maps the input voltage between 0 and the reference voltage to numbers between 0 and 1023. | ||
+ | |||
+ | By default, the reference voltage is set to a microcontroller operating voltage. Usually, it is 5 V or 3.3 V. Also, other internal or external reference sources can be used, for example, AREF pin. | ||
+ | |||
+ | <table Analog.pins> | ||
+ | < | ||
+ | ^ ^ <fs xx-small> | ||
+ | | <fs xx-small> | ||
+ | </ | ||
+ | |||
+ | ==== Power and Other Pins ==== | ||
+ | |||
+ | **Power pins** on the Arduino board connect the power source to the microcontroller and/or voltage regulators. They can also be used as a power source to the external components and devices. | ||
+ | |||
+ | The **VIN pin** is used to connect the external power source to the internal regulator, to provide the regulated 5 V output. The input voltage of the board must be within the specific range, mostly between 7 V and 12 V. | ||
+ | |||
+ | The **5V pin** is used to supply a microcontroller with the regulated 5 V from the external source or is used as a power source for the external components in the case when the board is already powered using the USB interface or the VIN pin. | ||
+ | |||
+ | The **3V3 pin** provides the regulated 3.3 V output for the board components and external devices. The GND (ground pin) is where the negative terminal of the power supply is applied. | ||
+ | |||
+ | The **Reset pin** and the reset button are used to reset the Arduino board and the program. Resetting using the reset pin is done by connecting it to the GND pin. | ||
+ | |||
+ | ==== Memory ==== | ||
+ | |||
+ | There are three different types of memory on the Arduino board: flash memory, SRAM and EEPROM. | ||
+ | |||
+ | The flash memory stores the Arduino code, and it is a non-volatile type of memory. That means the information in the memory is not deleted when the power is turned off. | ||
+ | |||
+ | The SRAM (static random access memory) is used for storing values of variables when the program of Arduino is running. This is the volatile memory that keeps information only until the power is turned off, or the board is reset. | ||
+ | |||
+ | The EEPROM (electrically erasable programmable read-only memory) is a non-volatile type of memory that can be used as the long-term memory storage. | ||
+ | |||
+ | <table Memory> | ||
+ | < | ||
+ | ^ ^ <fs xx-small> | ||
+ | | <fs xx-small> | ||
+ | | <fs xx-small> | ||
+ | | <fs xx-small> | ||
+ | </ | ||
+ | |||
+ | ==== Interface ==== | ||
+ | |||
+ | Communication interfaces for Arduino are used to send and receive information to and from other external devices. Standard interfaces for Arduino are USB, UART, I2C (two wire interface), SPI, Ethernet and WiFi.\\ | ||
+ | \\ | ||
+ | \\ | ||
+ | |||
+ | <table Interface> | ||
+ | < | ||
+ | ^ ^ <fs xx-small> | ||
+ | | <fs xx-small> | ||
+ | | <fs xx-small> | ||
+ | | <fs xx-small> | ||
+ | | <fs xx-small> | ||
+ | </ | ||
+ | |||
+ | ==== Size of the Board ==== | ||
+ | |||
+ | Arduino microcontrollers have different dimensions of the board, depending on the components that are located on the board. | ||
+ | |||
+ | <table Size> | ||
+ | < | ||
+ | ^ ^ <fs xx-small> | ||
+ | | <fs xx-small> | ||
+ | </ | ||
+ | |||
+ | ==== Arduino Shields ==== | ||
+ | Arduino shields are the extension boards that can be plugged on top of the Arduino board extending its capabilities. The shields can give additional functionality to the Arduino board. There are multiple categories of the Arduino shields ((https:// | ||
+ | |||
+ | **Prototyping shields** – are shields that do not give Arduino the additional functionality, | ||
+ | |||
+ | |||
+ | <figure label> | ||
+ | {{ : | ||
+ | < | ||
+ | </ | ||
+ | |||
+ | **Connectivity shields** – are shields that can add new functionalities to the Arduino board like Ethernet, WiFi, Wireless, GPS, etc. Example shields are Arduino Ethernet Shield, WiFly Shield, Arduino Wi-Fi Shield, Electric Imp Shield, XBee Shield, Cellular Shield SM5100B and GPS Shield. | ||
+ | |||
+ | <figure label> | ||
+ | {{ : | ||
+ | < | ||
+ | </ | ||
+ | |||
+ | **Displays and camera shields** – can provide Arduino with an LCD screen or add a camera. Example shields are Color LCD Shield, EL Escudo and CMUcam. | ||
+ | |||
+ | <figure label> | ||
+ | {{ : | ||
+ | < | ||
+ | </ | ||
+ | |||
+ | **Sound shields** – give the functionality to Arduino to play MP3 files, add speakers, listen to audio and sort it into different frequencies, | ||
+ | |||
+ | <figure label> | ||
+ | {{ : | ||
+ | < | ||
+ | </ | ||
+ | |||
+ | **Motor driver shields** – allow Arduino to control DC motors, Servo motors, Stepper motors. | ||
+ | |||
+ | <figure label> | ||
+ | {{ : | ||
+ | < | ||
+ | </ | ||
+ | ==== ==== | ||
+ | <box # | ||
+ | <box # | ||
+ | ==== Sensors and Sensing ==== | ||
+ | <box # | ||
+ | <box # | ||
+ | |||
+ | A sensor is an element which can turn a physical outer stimulus into an output signal which then can be used for further analysis, the management or decision making. People also use sensors like eyes, ears and skin for gaining information about the outer world and act accordingly to their aims and needs. Sensors can be divided into multiple categories by the parameter that is perceived from the environment. | ||
+ | |||
+ | <figure label> | ||
+ | {{ : | ||
+ | < | ||
+ | </ | ||
+ | |||
+ | Usually, every natural phenomenon – temperature, | ||
+ | |||
+ | === Touch Sensors === | ||
+ | == Button == | ||
+ | |||
+ | A **pushbutton** is an electromechanical sensor that connects or disconnects two points in a circuit when the force is applied. Button output discrete value is either //HIGH// or // | ||
+ | |||
+ | <figure label> | ||
+ | {{ : | ||
+ | < | ||
+ | </ | ||
+ | |||
+ | |||
+ | A **microswitch**, | ||
+ | |||
+ | <figure label> | ||
+ | {{ : | ||
+ | < | ||
+ | </ | ||
+ | |||
+ | The most common use of a pushbutton is as an input device. Both force solutions can be used as simple object detectors, or as end switches in the industrial devices. | ||
+ | |||
+ | <figure label> | ||
+ | {{ : | ||
+ | < | ||
+ | </ | ||
+ | |||
+ | An example code: | ||
+ | <code c> | ||
+ | |||
+ | int buttonPin = 2; // | ||
+ | int buttonState = 0; //A variable for reading the push button status | ||
+ | |||
+ | void setup() { | ||
+ | Serial.begin(9600); | ||
+ | pinMode(buttonPin, | ||
+ | } | ||
+ | |||
+ | void loop() { | ||
+ | //Read the state of the push button value | ||
+ | buttonState = !digitalRead(buttonPin); | ||
+ | //Check if the push button is pressed. If it is, the buttonState is HIGH | ||
+ | if (buttonState == HIGH) { | ||
+ | //Print out text in the console | ||
+ | Serial.println(" | ||
+ | } else { | ||
+ | Serial.println(" | ||
+ | } | ||
+ | delay(10); //Delay in between reads for stability | ||
+ | } | ||
+ | |||
+ | </ | ||
+ | |||
+ | ==Force Sensor== | ||
+ | |||
+ | A force sensor predictably changes resistance, depending on the applied force to its surface. Force-sensing resistors are manufactured in different shapes and sizes, and they can measure not only direct force but also the tension, compression, | ||
+ | |||
+ | Force sensors are used as control buttons or to determine weight. | ||
+ | |||
+ | <figure label> | ||
+ | {{ : | ||
+ | < | ||
+ | </ | ||
+ | |||
+ | <figure label> | ||
+ | {{ : | ||
+ | < | ||
+ | </ | ||
+ | |||
+ | An example code: | ||
+ | <code c> | ||
+ | |||
+ | //Force Sensitive Resistor (FSR) is connected to the analog 0 pin | ||
+ | int fsrPin = A0; | ||
+ | //The analog reading from the FSR resistor divider | ||
+ | int fsrReading; | ||
+ | |||
+ | void setup(void) { | ||
+ | //Begin serial communication | ||
+ | Serial.begin(9600); | ||
+ | // | ||
+ | pinMode(fsrPin, | ||
+ | } | ||
+ | |||
+ | void loop(void) { | ||
+ | //Read the resistance value of the FSR | ||
+ | fsrReading = analogRead(fsrPin); | ||
+ | // | ||
+ | Serial.print(" | ||
+ | Serial.println(fsrReading); | ||
+ | delay(10); | ||
+ | } | ||
+ | </ | ||
+ | |||
+ | ==Capacitive Sensor== | ||
+ | Capacitive sensors are a range of sensors that use capacitance to measure changes in the surrounding environment. A capacitive sensor consists of a capacitor that is charged with a certain amount of current until the threshold voltage. A human finger, liquids or other conductive or dielectric materials that touch the sensor, can influence a charge time and a voltage level in the sensor. Measuring charge time and a voltage level gives information about changes in the environment. | ||
+ | |||
+ | Capacitive sensors are used as input devices and can measure proximity, humidity, fluid level and other physical parameters or serve as an input for electronic device control. | ||
+ | |||
+ | <figure label> | ||
+ | {{ : | ||
+ | < | ||
+ | </ | ||
+ | |||
+ | <figure label> | ||
+ | {{ : | ||
+ | < | ||
+ | </ | ||
+ | |||
+ | <code c> | ||
+ | // | ||
+ | int touchPin = 2; | ||
+ | |||
+ | //The digital reading value from the sensor | ||
+ | boolean touchReading = LOW; | ||
+ | //The variable that stores the previous state value | ||
+ | boolean lastState = LOW; | ||
+ | |||
+ | void setup() { | ||
+ | //Begin serial communication | ||
+ | Serial.begin(9600); | ||
+ | // | ||
+ | pinMode(touchPin, | ||
+ | } | ||
+ | |||
+ | void loop() { | ||
+ | //Read the digital value of the capacitive sensor | ||
+ | touchReading = digitalRead(touchPin); | ||
+ | //If the new touch has appeared | ||
+ | if (currentState == HIGH && lastState == LOW){ | ||
+ | Serial.println(" | ||
+ | delay(10); //short delay | ||
+ | } | ||
+ | //Save previous state to see relative changes | ||
+ | lastState = currentState; | ||
+ | } | ||
+ | </ | ||
+ | |||
+ | === Light Sensors === | ||
+ | |||
+ | ==Photoresistor== | ||
+ | |||
+ | A photoresistor is a sensor that perceives light waves from the environment. The resistance of the photoresistor is changing depending on the intensity of light. The higher is the intensity of the light; the lower is the resistance of the sensor. A light level is determined by applying a constant voltage sensor and measuring it. Photodiodes, | ||
+ | |||
+ | Photoresistors are often used in the energy effective street lightning. | ||
+ | |||
+ | <figure label> | ||
+ | {{ : | ||
+ | < | ||
+ | </ | ||
+ | |||
+ | <figure label> | ||
+ | {{ : | ||
+ | < | ||
+ | </ | ||
+ | |||
+ | <figure label> | ||
+ | {{ : | ||
+ | < | ||
+ | </ | ||
+ | |||
+ | An example code: | ||
+ | <code c> | ||
+ | //Define an analog A0 pin for photoresistor | ||
+ | int photoresistorPin = A0; | ||
+ | //The analog reading from the photoresistor | ||
+ | int photoresistorReading; | ||
+ | |||
+ | void setup() | ||
+ | { | ||
+ | //Begin serial communication | ||
+ | Serial.begin(9600); | ||
+ | // | ||
+ | pinMode(photoresistorPin, | ||
+ | } | ||
+ | |||
+ | void loop() | ||
+ | { | ||
+ | //Read the value of the photoresistor | ||
+ | photoresistorReading = analogRead(photoresistorPin); | ||
+ | //Print out value of the photoresistor reading to the serial monitor | ||
+ | Serial.println(photoresistorReading); | ||
+ | delay(10); //Short delay | ||
+ | } | ||
+ | </ | ||
+ | |||
+ | ==Photodiode== | ||
+ | A photodiode is a sensor that converts the light energy into electrical current. A current in the sensor is generated by exposing a p-n junction of a semiconductor to the light. Information about the light intensity can be determined by measuring a voltage level. Photodiodes are reacting to the changes in the light intensity very quickly. Solar cells are just large photodiodes. | ||
+ | |||
+ | Photodiodes are used as precise light level sensors, receivers for remote control, electrical isolators and proximity detectors. | ||
+ | |||
+ | <figure label> | ||
+ | {{ : | ||
+ | < | ||
+ | </ | ||
+ | |||
+ | <figure label> | ||
+ | {{ : | ||
+ | < | ||
+ | </ | ||
+ | |||
+ | <figure label> | ||
+ | {{ : | ||
+ | < | ||
+ | </ | ||
+ | |||
+ | An example code: | ||
+ | <code c> | ||
+ | //Define an analog A0 pin for photodiode | ||
+ | int photodiodePin = A0; | ||
+ | //The analog reading from the photodiode | ||
+ | int photodiodeReading; | ||
+ | |||
+ | void setup() | ||
+ | { | ||
+ | //Begin serial communication | ||
+ | Serial.begin(9600); | ||
+ | // | ||
+ | pinMode(photodiodePin, | ||
+ | } | ||
+ | |||
+ | void loop() | ||
+ | { | ||
+ | //Read the value of the photodiode | ||
+ | photodiodeReading = analogRead(photodiodePin); | ||
+ | //Print out the value of the photodiode reading to the serial monitor | ||
+ | Serial.println(photodiodeReading); | ||
+ | delay(10); //Short delay | ||
+ | } | ||
+ | </ | ||
+ | |||
+ | ==Phototransistor== | ||
+ | A phototransistor is a light controlled electrical switch. In the exposed Base pin received light level, changes the amount of current, that can pass between two phototransistor pins – a collector and an emitter. A phototransistor is slower than the photodiode, but it can conduct more current. | ||
+ | |||
+ | Phototransistors are used as the optical switches, proximity sensors and electrical isolators. | ||
+ | |||
+ | <figure label> | ||
+ | {{ : | ||
+ | < | ||
+ | </ | ||
+ | |||
+ | <figure label> | ||
+ | {{ : | ||
+ | < | ||
+ | </ | ||
+ | |||
+ | <figure label> | ||
+ | {{ : | ||
+ | < | ||
+ | </ | ||
+ | |||
+ | An example code: | ||
+ | <code c> | ||
+ | //Define an analog A1 pin for phototransistor | ||
+ | int phototransistorPin = A1; | ||
+ | //The analog reading from the phototransistor | ||
+ | int phototransistorReading; | ||
+ | |||
+ | void setup() | ||
+ | { | ||
+ | //Begin serial communication | ||
+ | Serial.begin(9600); | ||
+ | // | ||
+ | pinMode(phototransistorPin, | ||
+ | } | ||
+ | |||
+ | void loop() | ||
+ | { | ||
+ | //Read the value of the phototransistor | ||
+ | phototransistorReading = analogRead(phototransistorPin); | ||
+ | //Print out the value of the phototransistor reading to the serial monitor | ||
+ | Serial.println(phototransistorReading); | ||
+ | delay(10); //short delay | ||
+ | } | ||
+ | </ | ||
+ | |||
+ | |||
+ | === Electrical Characteristic Sensors === | ||
+ | Electrical characteristic sensors are used to determine whether the circuit of the device is working properly. When the voltage and current sensors are used concurrently, | ||
+ | |||
+ | ==Voltage Sensor== | ||
+ | A voltage sensor is a device or circuit for voltage measurement. A simple DC (direct current) voltage sensor consists of a voltage divider circuit with the optional amplifier for very small voltage occasions. For measuring the AC (alternating current), a transformer is added to a lower voltage; then it is connected to the rectifier to rectify AC to DC, and finally, an optoelectrical isolator is added for measuring circuit safety. | ||
+ | |||
+ | A voltage sensor can measure electrical load and detect a power failure. Examples of IoT applications are monitoring of appliance, line power, power coupling, power supply and sump pump. | ||
+ | |||
+ | <figure label> | ||
+ | {{ : | ||
+ | < | ||
+ | </ | ||
+ | |||
+ | <figure label> | ||
+ | {{ : | ||
+ | < | ||
+ | </ | ||
+ | |||
+ | |||
+ | The example code: | ||
+ | |||
+ | <code c> | ||
+ | //Define an analog A1 pin for voltage sensor | ||
+ | int voltagePin = A1; | ||
+ | //The analog reading from the voltage sensor | ||
+ | int voltageReading; | ||
+ | |||
+ | float vout = 0.0; | ||
+ | float vin = 0.0; | ||
+ | float R1 = 30000.0; // 30 kΩ resistor | ||
+ | float R2 = 7500.0; // 7.5 kΩ resistor | ||
+ | |||
+ | void setup() | ||
+ | { | ||
+ | //Begin serial communication | ||
+ | Serial.begin(9600); | ||
+ | // | ||
+ | pinMode(voltagePin, | ||
+ | } | ||
+ | |||
+ | void loop() | ||
+ | { | ||
+ | //Read the value of the voltage sensor | ||
+ | voltageReading = analogRead(voltagePin); | ||
+ | vout = (voltageReading * 5.0) / 1024.0; | ||
+ | vin = vout / (R2/ | ||
+ | | ||
+ | Serial.print(" | ||
+ | //Print out the value of the voltage to the serial monitor | ||
+ | Serial.println(vin); | ||
+ | delay(10); //Short delay | ||
+ | } | ||
+ | </ | ||
+ | |||
+ | ==Current Sensor== | ||
+ | |||
+ | A current sensor is a device or a circuit for current measurement. A simple DC sensor consists of a high power resistor with low resistance. The current is obtained by measuring the voltage on the resistor and applying formula proportional to the voltage. Other non-invasive measurement methods involve hall effect sensors for DC and AC and inductive coils for AC. Current sensors are used to determine the power consumption, | ||
+ | |||
+ | <figure label> | ||
+ | {{ : | ||
+ | < | ||
+ | </ | ||
+ | |||
+ | <figure label> | ||
+ | {{ : | ||
+ | < | ||
+ | </ | ||
+ | |||
+ | The example code: | ||
+ | <code c> | ||
+ | //Define an analog A0 pin for current sensor | ||
+ | const int currentPin = A0; | ||
+ | //Scale factor of the sensor use 100 for 20 A Module and 66 for 30 A Module | ||
+ | int mVperAmp = 185; | ||
+ | int currentReading; | ||
+ | int ACSoffset = 2500; | ||
+ | double Voltage; | ||
+ | double Current; | ||
+ | |||
+ | void setup(){ | ||
+ | | ||
+ | } | ||
+ | |||
+ | void loop(){ | ||
+ | |||
+ | | ||
+ | | ||
+ | | ||
+ | |||
+ | | ||
+ | | ||
+ | | ||
+ | //The ' | ||
+ | | ||
+ | | ||
+ | </ | ||
+ | |||
+ | === Proximity and Distance Sensors === | ||
+ | |||
+ | ==Optocoupler== | ||
+ | |||
+ | An optocoupler is a device that combines light emitting and receiving devices. Mostly it is a combination of the infrared light-emitting diode (LED) and a phototransistor. Other optical semiconductors can be a photodiode and a photoresistor. There are two main types of optocouplers: | ||
+ | * an **optocoupler of a closed pair configuration** is enclosed in the dark resin and is used to transfer signals using light, ensuring electrical isolation between two circuits; | ||
+ | * a **slotted optocoupler** has a space between the light source and the sensor, light can be obstructed and thus can influence the sensor signal. It can be used to detect objects, rotation speed, vibrations or serve as a bounce-free switch; | ||
+ | * a **reflective pair configuration** the light signal is perceived as a reflection from the object surface. This configuration is used for proximity detection, surface colour detection and tachometer. | ||
+ | |||
+ | <figure label> | ||
+ | {{ : | ||
+ | < | ||
+ | </ | ||
+ | |||
+ | <figure label> | ||
+ | {{ : | ||
+ | < | ||
+ | </ | ||
+ | |||
+ | <figure label> | ||
+ | {{ : | ||
+ | < | ||
+ | </ | ||
+ | |||
+ | An example code: | ||
+ | <code c> | ||
+ | int optoPin = A0; // | ||
+ | int optoReading; | ||
+ | |||
+ | int objecttreshold = 1000; //Object threshold definition | ||
+ | int whitetreshold = 150; //White colour threshold definition | ||
+ | |||
+ | void setup () | ||
+ | { | ||
+ | //Begin serial communication | ||
+ | Serial.begin(9600); | ||
+ | // | ||
+ | pinMode(optoPin, | ||
+ | } | ||
+ | |||
+ | void loop () | ||
+ | { | ||
+ | optoReading = analogRead(optoPin); | ||
+ | Serial.print ("The reading of the optocoupler sensor is: "); | ||
+ | Serial.println(optoReading); | ||
+ | | ||
+ | //When the reading value is lower than the object threshold | ||
+ | if (optoReading < objecttreshold) { | ||
+ | Serial.println (" | ||
+ | //When the reading value is lower than the white colour threshold | ||
+ | if (optoReading < white threshold) { | ||
+ | Serial.println (" | ||
+ | } else { //When the reading value is higher than the white colout threshold | ||
+ | Serial.println (" | ||
+ | } | ||
+ | } | ||
+ | else { //When the reading value is higher than the object thershold | ||
+ | Serial.println (" | ||
+ | } | ||
+ | delay(500); //Short delay | ||
+ | } | ||
+ | </ | ||
+ | |||
+ | |||
+ | ==Infrared Sensor== | ||
+ | Infrared (IR) proximity sensor is used to detect objects and to measure the distance to them, without any physical contact. IR sensor consists of an infrared emitter, a receiving sensor or array of sensors and a signal processing logic. The output of a sensor differs depending on the type – simple proximity detection sensor outputs //HIGH// or //LOW// level when an object is in its sensing range, but sensors which can measure distance outputs an analogue signal or use some communication protocol, like I2C to send sensor measuring results. | ||
+ | IR sensors are used in robotics to detect obstacles starting from few millimetres to several meters and in mobile phones to help detect accidental button touching. | ||
+ | |||
+ | |||
+ | <figure label> | ||
+ | {{ : | ||
+ | < | ||
+ | </ | ||
+ | |||
+ | <figure label> | ||
+ | {{ : | ||
+ | < | ||
+ | </ | ||
+ | |||
+ | An example code: | ||
+ | <code c> | ||
+ | int irPin = A0; //Define an analog A0 pin for IR sensor | ||
+ | int irReading; | ||
+ | |||
+ | void setup() | ||
+ | { | ||
+ | //Begin serial communication | ||
+ | Serial.begin(9600); | ||
+ | // | ||
+ | pinMode(irPin, | ||
+ | } | ||
+ | |||
+ | void loop() | ||
+ | { | ||
+ | //Read the value of the IR sensor | ||
+ | irReading = analogRead(irPin); | ||
+ | //Print out the value of the IR sensor reading to the serial monitor | ||
+ | Serial.println(irReading); | ||
+ | delay(10); //Short delay | ||
+ | } | ||
+ | </ | ||
+ | |||
+ | ==Ultrasound Sensor== | ||
+ | Ultrasound (ultrasonic) sensor measures the distance to objects by emitting ultrasound and measuring its returning time. The sensor consists of an ultrasonic emitter and receiver; sometimes, they are combined in a single device for emitting and receiving. Ultrasonic sensors can measure greater distances and cost less than infrared sensors, but are more imprecise and interfere which each other measurement if more than one is used. Simple sensors have trigger pin and echo pin, when the trigger pin is set high for the small amount of time ultrasound is emitted and on echo pin, response time is measured. Ultrasonic sensors are used in car parking sensors and robots for proximity detection. | ||
+ | |||
+ | <figure label> | ||
+ | {{ : | ||
+ | < | ||
+ | </ | ||
+ | |||
+ | Examples of IoT applications are robotic obstacle detection and room layout scanning. | ||
+ | |||
+ | <figure label> | ||
+ | {{ : | ||
+ | < | ||
+ | </ | ||
+ | |||
+ | An example code: | ||
+ | <code c> | ||
+ | int trigPin = 2; //Define a trigger pin D2 | ||
+ | int echoPin = 4; //Define an echo pin D4 | ||
+ | |||
+ | void setup() | ||
+ | { | ||
+ | Serial.begin(9600); | ||
+ | pinMode(trigPin, | ||
+ | pinMode(echoPin, | ||
+ | } | ||
+ | |||
+ | void loop() | ||
+ | { | ||
+ | digitalWrite(trigPin, | ||
+ | delayMicroseconds(2); | ||
+ | | ||
+ | //Set the trigPin on HIGH state for 10 μs | ||
+ | digitalWrite(trigPin, | ||
+ | delayMicroseconds(10); | ||
+ | digitalWrite(trigPin, | ||
+ | | ||
+ | //Read the echoPin, return the sound wave travel time in microseconds | ||
+ | duration = pulseIn(echoPin, | ||
+ | // | ||
+ | distance= duration*0.034/ | ||
+ | | ||
+ | //Printing the distance on the Serial Monitor | ||
+ | Serial.print(" | ||
+ | Serial.println(distance); | ||
+ | } | ||
+ | </ | ||
+ | |||
+ | ==Motion Detector== | ||
+ | The motion detector is a sensor that detects moving objects, most people. Motion detectors use different technologies, | ||
+ | |||
+ | Motion sensors are used for security purposes, automated light and door systems. As an example in IoT, the PIR motion sensor can be used to detect motion in security systems a house or any building. | ||
+ | |||
+ | <figure label> | ||
+ | {{ : | ||
+ | < | ||
+ | </ | ||
+ | |||
+ | <figure label> | ||
+ | {{ : | ||
+ | < | ||
+ | </ | ||
+ | |||
+ | An example code: | ||
+ | <code c> | ||
+ | |||
+ | //Passive Infrared (PIR) sensor output is connected to the digital 2 pin | ||
+ | int pirPin = 2; | ||
+ | //The digital reading from the PIR output | ||
+ | int pirReading; | ||
+ | |||
+ | void setup(void) { | ||
+ | //Begin serial communication | ||
+ | Serial.begin(9600); | ||
+ | // | ||
+ | pinMode(pirPin, | ||
+ | } | ||
+ | |||
+ | void loop(void) { | ||
+ | //Read the digital value of the PIR motion sensor | ||
+ | pirReading = digitalRead(pirPin); | ||
+ | //Print out | ||
+ | Serial.print(" | ||
+ | Serial.println(pirReading); | ||
+ | |||
+ | if(pirReading == HIGH) { //Motion was detected | ||
+ | Serial.println(" | ||
+ | } | ||
+ | |||
+ | delay(10); | ||
+ | } | ||
+ | </ | ||
+ | |||
+ | |||
+ | === Angle Sensors === | ||
+ | |||
+ | ==Potentiometer== | ||
+ | A potentiometer is a type of resistor, the resistance of which can be adjusted using a mechanical lever. The device consists of three terminals. The resistor between the first and the third terminal has fixed value, but the second terminal is connected to the lever. Whenever the lever is turned, a slider of the resistor is moved, it changes the resistance between the second terminal and side terminals. Variable resistance causes the change of the voltage variable, and it can be measured to determine the position of the lever. Thus, potentiometer output is an analogue value. | ||
+ | |||
+ | Potentiometers are commonly used as a control level, for example, a volume level for the sound and joystick position. They can also be used for angle measurement in feedback loops with motors, for example, in servo motors. | ||
+ | |||
+ | <figure label> | ||
+ | {{ : | ||
+ | < | ||
+ | </ | ||
+ | |||
+ | <figure label> | ||
+ | {{ : | ||
+ | < | ||
+ | </ | ||
+ | |||
+ | <figure label> | ||
+ | {{ : | ||
+ | < | ||
+ | </ | ||
+ | |||
+ | An example code: | ||
+ | <code c> | ||
+ | |||
+ | // | ||
+ | int potentioPin = A0; | ||
+ | //The analog reading from the potentiometer output | ||
+ | int potentioReading; | ||
+ | |||
+ | void setup(void) { | ||
+ | //Begin serial communication | ||
+ | Serial.begin(9600); | ||
+ | // | ||
+ | pinMode(potentioPin, | ||
+ | } | ||
+ | |||
+ | void loop(void) { | ||
+ | //Read the analog value of the potentiometer sensor | ||
+ | potentioReading = analogRead(potentioPin); | ||
+ | Serial.print(" | ||
+ | Serial.println(potentioReading); | ||
+ | delay(10); | ||
+ | } | ||
+ | </ | ||
+ | |||
+ | ==The Inertial Measurement Unit (IMU)== | ||
+ | |||
+ | An IMU is an electronic device, that consist of accelerometer, | ||
+ | |||
+ | A **gyroscope** is a sensor that measures the angular velocity. The sensor is made of the microelectromechanical system (MEMS) technology and is integrated into the chip. The output of the sensor can be either analogue or digital value of information, | ||
+ | Gyroscope sensors are used in aviation, navigation and motion control. | ||
+ | |||
+ | A **magnetometer** is the sensor, that can measure the orientation of the device to the magnetic field of the Earth. A magnetometer is used in outdoor navigation for mobile devices, robots, quadcopters. | ||
+ | |||
+ | An **accelerometer** measures the acceleration of the object. The sensor uses a microelectromechanical system (MEMS) technology, where capacitive plates are attached to springs. When acceleration force is applied to the plates, the capacitance is changed; thus, it can be measured. Accelerometers can have 1 to 3 axis. On 3-axis, the accelerometer can detect orientation, | ||
+ | Accelerometers are used for measuring vibrations of cars, industrial devices, buildings and to detect volcanic activity. In IoT applications, | ||
+ | |||
+ | |||
+ | <figure label> | ||
+ | {{ : | ||
+ | < | ||
+ | </ | ||
+ | |||
+ | <figure label> | ||
+ | {{ : | ||
+ | < | ||
+ | </ | ||
+ | |||
+ | The example code: | ||
+ | <code c> | ||
+ | //Library for I2C communication | ||
+ | #include < | ||
+ | // | ||
+ | #include < | ||
+ | // | ||
+ | #include < | ||
+ | #include < | ||
+ | Adafruit_BNO055 bno = Adafruit_BNO055(55); | ||
+ | void setup(void) | ||
+ | { | ||
+ | bno.setExtCrystalUse(true); | ||
+ | } | ||
+ | void loop(void) | ||
+ | { | ||
+ | //Read sensor data | ||
+ | sensors_event_t event; | ||
+ | bno.getEvent(& | ||
+ | //Print X, Y And Z orientation | ||
+ | Serial.print(" | ||
+ | Serial.print(event.orientation.x, | ||
+ | Serial.print(" | ||
+ | Serial.print(event.orientation.y, | ||
+ | Serial.print(" | ||
+ | Serial.print(event.orientation.z, | ||
+ | Serial.println("" | ||
+ | delay(100); | ||
+ | } | ||
+ | |||
+ | </ | ||
+ | |||
+ | === Environment Sensors === | ||
+ | |||
+ | ==Temperature Sensor== | ||
+ | A temperature sensor is a device that is used to determine the temperature of the surrounding environment. Most temperature sensors work on the principle that the resistance of the material is changed depending on its temperature. The most common temperature sensors are: | ||
+ | * **thermocouple** – consists of two junctions of dissimilar metals, | ||
+ | * **thermistor** – includes the temperature-dependent ceramic resistor, | ||
+ | * **resistive temperature detector** – is made of a pure metal coil. | ||
+ | The main difference between sensors is the measured temperature range, precision and response time. Temperature sensor usually outputs the analogue value, but some existing sensors have a digital interface ((http:// | ||
+ | |||
+ | The temperature sensors most commonly are used in environmental monitoring devices and thermoelectric switches. In IoT applications, | ||
+ | |||
+ | <figure label> | ||
+ | {{ : | ||
+ | < | ||
+ | </ | ||
+ | |||
+ | <figure label> | ||
+ | {{ : | ||
+ | < | ||
+ | </ | ||
+ | |||
+ | An example code: | ||
+ | <code c> | ||
+ | |||
+ | // | ||
+ | int thermoPin = 0; | ||
+ | //The analog reading from the thermistor output | ||
+ | int thermoReading; | ||
+ | |||
+ | void setup(void) { | ||
+ | //Begin serial communication | ||
+ | Serial.begin(9600); | ||
+ | // | ||
+ | pinMode(thermoPin, | ||
+ | } | ||
+ | |||
+ | void loop(void) { | ||
+ | //Read the analog value of the thermistor sensor | ||
+ | thermoReading = analogRead(thermoPin); | ||
+ | Serial.print(" | ||
+ | Serial.println(thermoReading); | ||
+ | delay(10); | ||
+ | } | ||
+ | </ | ||
+ | |||
+ | ==Humidity Sensor== | ||
+ | A humidity sensor (hygrometer) is a sensor that detects the amount of water or water vapour in the environment. The most common principle of the air humidity sensors is the change of capacitance or resistance of materials that absorb the moisture from the environment. Soil humidity sensors measure the resistance between the two electrodes. The resistance between electrodes is influenced by soluble salts and water amount in the soil. The output of a humidity sensor is usually an analogue signal value ((https:// | ||
+ | |||
+ | Example IoT applications are monitoring of humidor, greenhouse temperature and humidity, agriculture, | ||
+ | |||
+ | <figure label> | ||
+ | {{ : | ||
+ | < | ||
+ | </ | ||
+ | |||
+ | <figure label> | ||
+ | {{ : | ||
+ | < | ||
+ | </ | ||
+ | |||
+ | An example code ((http:// | ||
+ | <code c> | ||
+ | #include < | ||
+ | |||
+ | dht DHT; | ||
+ | |||
+ | #define DHT_PIN 7 | ||
+ | |||
+ | void setup(){ | ||
+ | Serial.begin(9600); | ||
+ | } | ||
+ | |||
+ | void loop() | ||
+ | { | ||
+ | int chk = DHT.read11(DHT_PIN); | ||
+ | Serial.print(" | ||
+ | Serial.println(DHT.humidity); | ||
+ | delay(1000); | ||
+ | } | ||
+ | </ | ||
+ | |||
+ | ==Sound Sensor== | ||
+ | A sound sensor is a sensor that detects vibrations in a gas, liquid or solid environments. At first, the sound wave pressure makes mechanical vibrations, who transfers to changes in capacitance, | ||
+ | |||
+ | Sound sensors are used in drone detection, gunshot alert, seismic detection and vault safety alarm. | ||
+ | |||
+ | <figure label> | ||
+ | {{ : | ||
+ | < | ||
+ | </ | ||
+ | |||
+ | <figure label> | ||
+ | {{ : | ||
+ | < | ||
+ | </ | ||
+ | |||
+ | An example code: | ||
+ | <code c> | ||
+ | //Sound sensor output is connected to the digital 7 pin | ||
+ | int soundPin = 7; | ||
+ | //Stores sound sensor detection readings | ||
+ | int soundReading = HIGH; | ||
+ | |||
+ | void setup(void) { | ||
+ | //Begin serial communication | ||
+ | Serial.begin(9600); | ||
+ | // | ||
+ | pinMode(soundPin, | ||
+ | } | ||
+ | |||
+ | void loop(void) { | ||
+ | //Read the digital value whether the sound has been detected | ||
+ | soundReading = digitalRead(soundPin); | ||
+ | if (soundPin==LOW) { //When sound detector detected the sound | ||
+ | Serial.println(" | ||
+ | } else { //When the sound is not detected | ||
+ | Serial.println(" | ||
+ | } | ||
+ | delay(10); | ||
+ | } | ||
+ | </ | ||
+ | |||
+ | |||
+ | ==Chemical/ | ||
+ | Gas sensors are a sensor group, that can detect and measure a concentration of certain gasses in the air. The working principle of electrochemical sensors is to absorb the gas and to create current from an electrochemical reaction. For process acceleration, | ||
+ | |||
+ | Gas sensors are used for safety devices, to control air quality and for manufacturing equipment. Examples of IoT applications are air quality control management in smart buildings and smart cities or toxic gas detection in sewers and underground mines. | ||
+ | |||
+ | <figure label> | ||
+ | {{ : | ||
+ | < | ||
+ | </ | ||
+ | |||
+ | <figure label> | ||
+ | {{ : | ||
+ | < | ||
+ | </ | ||
+ | |||
+ | An example code: | ||
+ | <code c> | ||
+ | int gasPin = A0; //Gas sensor output is connected to the analog A0 pin | ||
+ | int gasReading; //Stores gas sensor detection reading | ||
+ | |||
+ | void setup(void) { | ||
+ | Serial.begin(9600); | ||
+ | pinMode(gasPin, | ||
+ | } | ||
+ | |||
+ | void loop(void) { | ||
+ | gasReading = analogRead(gasPin); | ||
+ | Serial.print(" | ||
+ | Serial.println(gasReading); | ||
+ | delay(10); //Short delay | ||
+ | } | ||
+ | </ | ||
+ | |||
+ | ==Level Sensor== | ||
+ | A level sensor detects the level of fluid or fluidised solid. Level sensors can be divided into two groups: | ||
+ | * **continuous level sensors** that can detect the exact position of the fluid. For the level detection usually, the proximity sensors, like ultrasonic or infrared, are used. Capacitive sensors can also be used by recording the changing capacitance value depending on the fluid level. The output can be either analogue or digital value; | ||
+ | * **point-level sensors** can detect whether a fluid is above or below the sensor. For the level detection, float or mechanical switch, diaphragm with air pressure or changes in conductivity or capacitance, | ||
+ | |||
+ | Level sensors can be used as smart waste management, for measuring tank levels, diesel fuel gauging, liquid assets inventory, chemical manufacturing high or low-level alarms and irrigation control. | ||
+ | |||
+ | |||
+ | <figure label> | ||
+ | {{ : | ||
+ | < | ||
+ | </ | ||
+ | |||
+ | |||
+ | |||
+ | <figure label> | ||
+ | {{ : | ||
+ | < | ||
+ | </ | ||
+ | |||
+ | An example code: | ||
+ | <code c> | ||
+ | int levelPin = 6; //Liquid level sensor output is connected to the digital 6 pin | ||
+ | int levelReading; | ||
+ | |||
+ | void setup(void) { | ||
+ | Serial.begin(9600); | ||
+ | pinMode(levelPin, | ||
+ | } | ||
+ | |||
+ | void loop(void) { | ||
+ | levelReading = digitalRead(levelPin); | ||
+ | Serial.print(" | ||
+ | Serial.println(levelReading); | ||
+ | delay(10); //Short delay | ||
+ | } | ||
+ | </ | ||
+ | |||
+ | === Other Sensors === | ||
+ | |||
+ | ==Hall sensor== | ||
+ | A **Hall effect sensor** detects strong magnetic fields, their polarities and the relative strength of the field. In the Hall effect sensors, a magnetic force influences current flow through the semiconductor material and creates a measurable voltage on the sides of the semiconductor. Sensors with analogue output can measure the strength of the magnetic field, while digital sensors give //HIGH// or //LOW// output value, depending on the presence of the magnetic field. | ||
+ | |||
+ | Hall effect sensors are used in magnetic encoders for speed measurements and magnetic proximity switches because it does not require contact, and it ensures high reliability. Example application can be sensing the position of rotary valves. | ||
+ | |||
+ | <figure label> | ||
+ | {{ : | ||
+ | < | ||
+ | </ | ||
+ | |||
+ | <figure label> | ||
+ | {{ : | ||
+ | < | ||
+ | </ | ||
+ | |||
+ | Thw example code: | ||
+ | <code c> | ||
+ | int hallPin = A0; //Hall sensor output is connected to the analog A0 pin | ||
+ | int hallReading; | ||
+ | |||
+ | void setup(void) { | ||
+ | Serial.begin(9600); | ||
+ | pinMode(hallPin, | ||
+ | } | ||
+ | |||
+ | void loop(void) { | ||
+ | hallReading = analogRead(hallPin); | ||
+ | Serial.print(" | ||
+ | Serial.println(hallReading); | ||
+ | delay(10); //Short delay | ||
+ | } | ||
+ | </ | ||
+ | |||
+ | ==Global Positioning System== | ||
+ | A GPS receiver is a device, that can receive information from a global navigation satellite system and calculate its position on the Earth. | ||
+ | |||
+ | A GPS receiver is used for device location tracking. Real world applications might be, i.e., pet, kid or personal belonging location tracking. | ||
+ | |||
+ | <figure label> | ||
+ | {{ : | ||
+ | < | ||
+ | </ | ||
+ | |||
+ | |||
+ | <figure label> | ||
+ | {{ : | ||
+ | < | ||
+ | </ | ||
+ | |||
+ | The example code ((http:// | ||
+ | <code c> | ||
+ | #include < | ||
+ | SoftwareSerial SoftSerial(2, | ||
+ | unsigned char buffer[64]; | ||
+ | int count=0; | ||
+ | void setup() | ||
+ | { | ||
+ | SoftSerial.begin(9600); | ||
+ | Serial.begin(9600); | ||
+ | } | ||
+ | |||
+ | void loop() | ||
+ | { | ||
+ | if (SoftSerial.available()) | ||
+ | // ==> Data is coming from SoftSerial shield | ||
+ | { | ||
+ | while(SoftSerial.available()) | ||
+ | { | ||
+ | buffer[count++]=SoftSerial.read(); | ||
+ | if(count == 64)break; | ||
+ | } | ||
+ | Serial.write(buffer, | ||
+ | // | ||
+ | clearBufferArray(); | ||
+ | //The stored data from the array | ||
+ | count = 0; //Set counter of while loop to zero | ||
+ | } | ||
+ | if (Serial.available()) | ||
+ | // ==> Data is coming from PC or notebook | ||
+ | SoftSerial.write(Serial.read()); | ||
+ | } | ||
+ | |||
+ | |||
+ | void clearBufferArray() | ||
+ | { | ||
+ | for (int i=0; i< | ||
+ | { | ||
+ | buffer[i]=NULL; | ||
+ | } // | ||
+ | } | ||
+ | </ | ||
+ | ==== ==== | ||
+ | <box # | ||
+ | <box # | ||
+ | ==== Drivers and Driving ==== | ||
+ | <box # | ||
+ | <box # | ||
+ | |||
+ | === Optical Device Drivers and Their Devices === | ||
+ | |||
+ | == Light-Emitting Diode == | ||
+ | The light-emitting diode also called LED is a special type of diodes which emits light, unlike the other diodes. LED has a completely different body which is made of transparent plastic that protects the diode and lets it emit light. Like the other diodes LED conducts the current in only one way, so it is essential to connect it to the scheme correctly. There are two safe ways how to determine the direction of the diode: | ||
+ | * in the cathodes side of the diode its side is chipped, | ||
+ | * anodes leg usually is longer than the cathodes leg. | ||
+ | |||
+ | <figure label> | ||
+ | {{ : | ||
+ | < | ||
+ | </ | ||
+ | |||
+ | The LED is one of the best light sources. Unlike incandescent light bulb LED transforms most of the power into light, not warmth; it is more durable, works for a more extended period and can be manufactured in a smaller size. | ||
+ | |||
+ | The LED colour is determined by the semiconductors material. Diodes are usually made from silicon then LEDs are made from elements like gallium phosphate, silicon carbide and others. Because the semiconductors used are different, the voltage needed for the LED to shine is also different. In the table, you can see with which semiconductor you can get a specific colour and the voltage required to turn on the LED. | ||
+ | |||
+ | When LED is connected to the voltage and turned on a huge current starts to flow through it, and it can damage the diode. That is why all **LEDs have to be connected to current limiting resistor**. | ||
+ | |||
+ | Current limiting resistors resistance is determined by three parameters: | ||
+ | * //I_D// – current that can flow through the LED, | ||
+ | * //U_D// – Voltage that is needed to turn on the LED, | ||
+ | * //U// – combined voltage for LED and resistor. | ||
+ | |||
+ | To calculate the resistance needed for a diode, this is what you have to do. | ||
+ | - Find out the voltage needed for the diode to work UD; you can find it in the diodes parameters table. | ||
+ | - Find out the amperage needed for the LED to shine ID; it can be found in the LEDs datasheet, but if you can’t find it then 20 mA current is usually a correct and safe choice. | ||
+ | - Find out the combined voltage for the LED and resistor; usually, it is the feeding voltage for the scheme. | ||
+ | - Insert all the values into this equation: //R = (U – U_D) / I_D// | ||
+ | - You get the resistance for the resistor for the safe use of the LED. | ||
+ | - Find resistors nominal that is the same or bigger than the calculated resistance. | ||
+ | |||
+ | <figure label> | ||
+ | {{ : | ||
+ | < | ||
+ | </ | ||
+ | |||
+ | The example of the blinking LED code: | ||
+ | <code c> | ||
+ | int ledPin = 8;// | ||
+ | |||
+ | void setup() | ||
+ | { | ||
+ | pinMode(ledPin, | ||
+ | } | ||
+ | |||
+ | void loop() | ||
+ | { | ||
+ | //Set pin output signal to HIGH – LED is working | ||
+ | digitalWrite(ledPin, | ||
+ | //Belay of 1000 ms | ||
+ | delay(1000); | ||
+ | |||
+ | //Set pin output signal to LOW – LED is not working | ||
+ | digitalWrite(ledPin, | ||
+ | //Delay of 1000 ms | ||
+ | delay(1000); | ||
+ | } | ||
+ | </ | ||
+ | |||
+ | == Displays == | ||
+ | |||
+ | Using display is a quick way to get feedback information from the device. There are many display technologies compatible with Arduino. For IoT solutions, low power, easy to use and monochrome displays are used: | ||
+ | * liquid-crystal display (LCD), | ||
+ | * organic light-emitting diode display (OLED), | ||
+ | * electronic ink display (E-ink). | ||
+ | |||
+ | **Liquid-Crystal Display (LCD)** | ||
+ | |||
+ | LCD uses modulating properties of liquid crystal light to block the incoming light. Thus when a voltage is applied to a pixel, it has a dark colour. A display consists of layers of electrodes, polarising filters, liquid crystals and reflector or back-light. Liquid crystals do not emit the light directly; they do it through reflection or backlight. Because of this reason, they are more energy efficient. Small, monochrome LCDs are widely used in devices to show a little numerical or textual information like temperature, | ||
+ | |||
+ | <figure label> | ||
+ | {{ : | ||
+ | < | ||
+ | </ | ||
+ | |||
+ | <figure label> | ||
+ | {{ : | ||
+ | < | ||
+ | </ | ||
+ | |||
+ | The example code: | ||
+ | <code c> | ||
+ | #include < | ||
+ | |||
+ | //Define LCD pins | ||
+ | const int rs = 12, en = 11, d4 = 5, d5 = 4, d6 = 3, d7 = 2; | ||
+ | //Create and LCD object with predefined pins | ||
+ | LiquidCrystal lcd(rs, en, d4, d5, d6, d7); | ||
+ | |||
+ | void setup() { | ||
+ | lcd.begin(16, | ||
+ | lcd.print(" | ||
+ | } | ||
+ | |||
+ | void loop() { | ||
+ | //Set the cursor to column 0, line 1 – line 1 is the second row | ||
+ | //Since counting begins with 0 | ||
+ | lcd.setCursor(0, | ||
+ | //Print the number of seconds since reset | ||
+ | lcd.print(millis() / 1000); | ||
+ | } | ||
+ | </ | ||
+ | |||
+ | **Organic Light-Emitting Diode Display (OLED)** | ||
+ | |||
+ | OLED display uses electroluminescent materials that emit light when the current passes through these materials. The display consists of two electrodes and a layer of an organic compound. OLED displays are thinner than LCDs, they have higher contrast, and they can be more energy efficient depending on usage. OLED displays are commonly used in mobile devices like smartwatches, | ||
+ | |||
+ | <figure label> | ||
+ | {{ : | ||
+ | < | ||
+ | </ | ||
+ | |||
+ | <figure label> | ||
+ | {{ : | ||
+ | < | ||
+ | </ | ||
+ | |||
+ | <code c> | ||
+ | //Add libraries to ensure the functioning of OLED | ||
+ | #include < | ||
+ | #include < | ||
+ | #include < | ||
+ | #define OLED_RESET 4 | ||
+ | Adafruit_SSD1306 display(OLED_RESET); | ||
+ | |||
+ | void setup() { | ||
+ | //Setting up initial OLED parameters | ||
+ | display.begin(SSD1306_SWITCHCAPVCC, | ||
+ | display.setTextSize(1); | ||
+ | display.setTextColor(WHITE); | ||
+ | |||
+ | void loop() { | ||
+ | |||
+ | //Print out on display output sensor values | ||
+ | display.setCursor(0, | ||
+ | display.clearDisplay(); | ||
+ | display.print(" | ||
+ | display.display(); | ||
+ | delay(100); | ||
+ | display.clearDisplay(); | ||
+ | } | ||
+ | </ | ||
+ | |||
+ | |||
+ | **Electronic Ink Display (E-Ink)** | ||
+ | |||
+ | E-ink display uses charged particles to create a paper-like effect. The display consists of transparent microcapsules filled with oppositely charged white and black particles between electrodes. Charged particles change their location, depending on the orientation of the electric field, thus individual pixels can be either black or white. The image does not need the power to persist on the screen; power is used only when the image is changed. Thus e-ink display is very energy efficient. It has high contrast and viewing angle, but it has a low refresh rate. E-ink displays are commonly used in e-riders, smartwatches, | ||
+ | |||
+ | <figure label> | ||
+ | {{ : | ||
+ | < | ||
+ | </ | ||
+ | |||
+ | <figure label> | ||
+ | {{ : | ||
+ | < | ||
+ | </ | ||
+ | |||
+ | <code c> | ||
+ | #include < | ||
+ | #include < | ||
+ | |||
+ | E_ink Eink; | ||
+ | |||
+ | void setup() | ||
+ | { | ||
+ | //BS LOW for 4 line SPI | ||
+ | pinMode(8, | ||
+ | digitalWrite(8, | ||
+ | | ||
+ | Eink.InitEink(); | ||
+ | |||
+ | Eink.ClearScreen();// | ||
+ | |||
+ | Eink.EinkP8x16Str(14, | ||
+ | Eink.EinkP8x16Str(10, | ||
+ | Eink.EinkP8x16Str(6, | ||
+ | Eink.EinkP8x16Str(2, | ||
+ | |||
+ | Eink.RefreshScreen(); | ||
+ | } | ||
+ | void loop() | ||
+ | { | ||
+ | |||
+ | } | ||
+ | </ | ||
+ | |||
+ | === Mechanical Drivers === | ||
+ | |||
+ | == Relay == | ||
+ | |||
+ | Relays are electromechanical devices that use electromagnets to connect or disconnect plates of a switch. Relays are used to control high power circuits with low power circuits. Circuits are mechanically isolated and thus protect logic control. Relays are used in household appliance automation, lighting and climate control. | ||
+ | |||
+ | <figure label> | ||
+ | {{ : | ||
+ | < | ||
+ | </ | ||
+ | |||
+ | <figure label> | ||
+ | {{ : | ||
+ | < | ||
+ | </ | ||
+ | |||
+ | The example code: | ||
+ | <code c> | ||
+ | #define relayPin | ||
+ | | ||
+ | void setup() | ||
+ | { | ||
+ | Serial.begin(9600); | ||
+ | pinMode(relayPin, | ||
+ | |||
+ | } | ||
+ | |||
+ | void loop() | ||
+ | { | ||
+ | | ||
+ | | ||
+ | | ||
+ | |||
+ | | ||
+ | | ||
+ | | ||
+ | } | ||
+ | </ | ||
+ | |||
+ | |||
+ | == Solenoid == | ||
+ | Solenoids are devices that use electromagnets to pull or push iron or steel core. They are used as linear actuators for locking mechanisms indoors, pneumatic and hydraulic valves and in-car starter systems. | ||
+ | |||
+ | Solenoids and relays both use electromagnets and connecting them to Arduino is very similar. Coils need a lot of power, and they are usually attached to the power source of the circuit. Turning the power of the coil off makes the electromagnetic field to collapse and creates very high voltage. For the semiconductor devices protection, a shunt diode is used to channel the overvoltage. For extra safety, optoisolator can be used. | ||
+ | |||
+ | <figure label> | ||
+ | {{ : | ||
+ | < | ||
+ | </ | ||
+ | |||
+ | <figure label> | ||
+ | {{ : | ||
+ | < | ||
+ | </ | ||
+ | |||
+ | The example code: | ||
+ | <code c> | ||
+ | #define solenoidPin | ||
+ | | ||
+ | void setup() | ||
+ | { | ||
+ | Serial.begin(9600); | ||
+ | pinMode(solenoidPin, | ||
+ | |||
+ | } | ||
+ | |||
+ | void loop() | ||
+ | { | ||
+ | | ||
+ | | ||
+ | | ||
+ | |||
+ | | ||
+ | | ||
+ | | ||
+ | } | ||
+ | </ | ||
+ | |||
+ | |||
+ | == Speaker == | ||
+ | Speakers are electroacoustic devices that convert the electrical signal into sound waves. A speaker uses a permanent magnet and a coil attached to the membrane. Sound signal, flowing through the coil, creates the electromagnetic field with variable strength, coil attracts to magnet according to the strength of the field, thus making a membrane to vibrate and creating a sound wave. Other widely used speaker technology, called Piezo speaker, uses piezoelectric materials instead of magnets. Speakers are used to creating an audible sound for human perception and ultrasonic sound for sensors and measurement equipment. | ||
+ | |||
+ | <figure label> | ||
+ | {{ : | ||
+ | < | ||
+ | </ | ||
+ | |||
+ | <figure label> | ||
+ | {{ : | ||
+ | < | ||
+ | </ | ||
+ | |||
+ | <code c> | ||
+ | const int speakerPin = 9; //Define the buzzer pin | ||
+ | |||
+ | void setup() | ||
+ | { | ||
+ | pinMode(speakerPin, | ||
+ | } | ||
+ | |||
+ | void loop() | ||
+ | { | ||
+ | tone(speakerrPin, | ||
+ | delay(1000); | ||
+ | noTone(speakerPin); | ||
+ | delay(1000); | ||
+ | } | ||
+ | </ | ||
+ | |||
+ | == DC Motor (One Direction) == | ||
+ | An electric motor is an electro-technical device which can turn electrical energy into mechanical energy; motor turns because of the electricity that flows in its winding. Electric motors have seen many technical solutions over the year from which the simplest is the permanent-magnet DC motor. | ||
+ | |||
+ | DC motor is a device which converts direct current into the mechanical rotation. DC motor consists of permanent magnets in stator and coils in the rotor. By applying the current to coils, the electromagnetic field is created, and the rotor tries to align itself to the magnetic field. Each coil is connected to a commutator, which in turns supplies coils with current, thus ensuring continuous rotation. DC motors are widely used in power tools, toys, electric cars, robots, etc. | ||
+ | |||
+ | <figure label> | ||
+ | {{ : | ||
+ | < | ||
+ | </ | ||
+ | |||
+ | <figure label> | ||
+ | {{ : | ||
+ | < | ||
+ | </ | ||
+ | |||
+ | <code c> | ||
+ | void setup () | ||
+ | { | ||
+ | pinMode(5, | ||
+ | //The function for turning on the motor is defined | ||
+ | #define motON digitalWrite(5, | ||
+ | //The function for turning off the motor is defined | ||
+ | #define motOFF digitalWrite(5, | ||
+ | } | ||
+ | void loop () | ||
+ | { | ||
+ | motON; //Turn on the motor | ||
+ | } | ||
+ | |||
+ | </ | ||
+ | |||
+ | |||
+ | == DC Motor With H-Bridge == | ||
+ | |||
+ | The H-bridge has earned its name because of its resemblance to the capital ‘H’ wherein all the corners there are switches and in the middle – the electric motor. This bridge is usually used for operating permanent-magnet DC motor, electromagnets and other similar elements, because it allows operating with significantly bigger current devices, using a small current. | ||
+ | By switching the switches, it is possible to change the motor direction. It is important to keep in mind that the switches need to be turned on and off in pairs. | ||
+ | |||
+ | When all of the switches are turned off, the engine is in the free movement. To slow down faster, the H-bridge is turned on in the opposite direction. | ||
+ | |||
+ | <figure label> | ||
+ | {{ : | ||
+ | < | ||
+ | </ | ||
+ | |||
+ | If both positive or both negative switches are turned on at the top or at the bottom, then the engine stops, not allowing to have a free rotation – it is slowed down. The management can be reflected in Table 10. | ||
+ | |||
+ | When all of the switches are turned off, the engine is in the free movement. Not always it is enough for robotics, so sometimes the H-bridge is turned on in the opposite direction to slow the motor down faster – the opposite direction is turned on rapidly. | ||
+ | |||
+ | <table label> | ||
+ | < | ||
+ | ^ Upper left ^ Upper right ^ Lower left ^ Lower right ^ Motor work mode ^ | ||
+ | | **On** | Off | Off | **On** | **Turns in one direction** | | ||
+ | | Off | **On** | **On** | Off | **Turns in another direction** | | ||
+ | | **On** | **On** | Off | Off | Braking | | ||
+ | | Off | Off | **On** | **On** | Braking | | ||
+ | </ | ||
+ | |||
+ | |||
+ | **Remember!** Neither of these braking mechanisms is good for the H-bridge or the power source. That is why this action is unacceptable without a particular reason because it can damage the switches or the power source. | ||
+ | |||
+ | The complicated part is the realisation of switches – if the switches don’t work usually relays or appropriate power transistors are used. The biggest drawback for relays is that they can only turn the engine on or off. If the rotation speed needs to be regulated using the impulse width modulation, then transistors have to be used. MOSFET type transistors should be used for ensuring a large amount of power. | ||
+ | Nowadays, the stable operation of the bridge is ensured by adding extra elements. The manufactured bridges have one body, for example, the one that is included in the constructor – L293D. | ||
+ | |||
+ | <figure label> | ||
+ | {{ : | ||
+ | < | ||
+ | </ | ||
+ | |||
+ | The L293D microchip consists of two H-bridges and is made for managing two motors. Each pin of the microchip has its function; that is why it is very important not to mix them up; otherwise, the microchip can be damaged. All pins of the microchip have assigned a number. The enumeration begins with the special mark on the body: a split, a dot, a cracked edge, etc., and continues counter-clockwise. When creating a scheme, it is important to take into account pin numbers and the ones shown in the scheme. If some additional information about the microchip is necessary, it can be found in the datasheet of the microchip. Remember that the datasheet can be found by writing the number of the device (written on the body) and adding the word " | ||
+ | |||
+ | <figure label> | ||
+ | {{ : | ||
+ | < | ||
+ | </ | ||
+ | |||
+ | The example code: | ||
+ | <code c> | ||
+ | int dirPin1 = 7; //1st direction pin | ||
+ | int dirPin2 = 8; //2nd direction pin | ||
+ | int speedPin = 5; //Pin responsible for the motor speed | ||
+ | |||
+ | void setup () | ||
+ | { | ||
+ | pinMode (dirPin1, | ||
+ | pinMode (dirPin2, | ||
+ | pinMode (speedPin, | ||
+ | } | ||
+ | |||
+ | void loop () | ||
+ | { | ||
+ | analogWrite(speedPin, | ||
+ | //Speed value can be from 0 to 255 | ||
+ | | ||
+ | int motDirection = 1; //Motor direction can be either 0 or 1 | ||
+ | | ||
+ | if (motDirection) //Setting motor direction | ||
+ | {//If 1 | ||
+ | digitalWrite(dirPin1, | ||
+ | digitalWrite(dirPin2, | ||
+ | } | ||
+ | else | ||
+ | {//If 0 | ||
+ | digitalWrite(dirPin1, | ||
+ | digitalWrite(dirPin2, | ||
+ | } | ||
+ | } | ||
+ | |||
+ | </ | ||
+ | |||
+ | |||
+ | == Stepper Motor == | ||
+ | |||
+ | Stepper motors are motors, that can be moved by a certain angle or step. Full rotation of the motor is divided into small, equal steps. Stepper motor has many individually controlled electromagnets, | ||
+ | Example of use can be found in the source ((https:// | ||
+ | |||
+ | <figure label> | ||
+ | {{ : | ||
+ | < | ||
+ | </ | ||
+ | |||
+ | <figure label> | ||
+ | {{ : | ||
+ | < | ||
+ | </ | ||
+ | |||
+ | The example code: | ||
+ | <code c> | ||
+ | #include < | ||
+ | |||
+ | int in1Pin = 12; //Defining stepper motor pins | ||
+ | int in2Pin = 11; | ||
+ | int in3Pin = 10; | ||
+ | int in4Pin = 9; | ||
+ | |||
+ | //Define a stepper motor object | ||
+ | Stepper motor(512, in1Pin, in2Pin, in3Pin, in4Pin); | ||
+ | |||
+ | void setup() | ||
+ | { | ||
+ | pinMode(in1Pin, | ||
+ | pinMode(in2Pin, | ||
+ | pinMode(in3Pin, | ||
+ | pinMode(in4Pin, | ||
+ | |||
+ | Serial.begin(9600); | ||
+ | motor.setSpeed(20); | ||
+ | } | ||
+ | |||
+ | void loop() | ||
+ | { | ||
+ | motor.step(5); | ||
+ | } | ||
+ | </ | ||
+ | |||
+ | |||
+ | == Servomotor == | ||
+ | |||
+ | Unlike the simple DC motor, the servomotor is a particular management chain which allows effortless control over the speed or position of the motor. The management of the engine is realised using three connections – positive (usually red) and negative connection (brown or black) of the current as well as the connection for management (orange or yellow). | ||
+ | |||
+ | For the management, the pulse width technique is used. | ||
+ | |||
+ | <figure label> | ||
+ | {{ : | ||
+ | < | ||
+ | </ | ||
+ | |||
+ | From the image, it can be seen that the length of the servomotor impulse cycle is 20 ms, but the impulse length itself is 1 ms or 2 ms. These signal characteristics are true for the most enthusiast level servomotors, | ||
+ | Servomotor management chain meets the impulse every 20 ms, but the width of the pulse shows the position that the servomotor has to reach. For example, 1 ms corresponds to the 0° position but 2 ms – to 180° position against the starting point. When entering the defined position, the servomotor will keep it and resist any outer forces that are trying to change the current position. The graphical representation is in the following image. | ||
+ | |||
+ | <figure label> | ||
+ | {{ : | ||
+ | < | ||
+ | </ | ||
+ | |||
+ | Just like other motors, servomotors have different parameters, where the most important one is the time of performance – the time that is necessary to change the position to the defined position. The best enthusiast level servomotors do a 60° turn in 0.09 s. There are three types of servomotors: | ||
+ | * **positional rotation servomotor** – most widely used type of servomotor. With the help of a management signal, it can determine the position of the rotation axis from its starting position; | ||
+ | * **continuous rotation servomotor** – this type of motor allows setting the speed and direction of the rotation using the management signal. If the position is less than 90°, it turns in one direction, but if more than 90° it turns in the opposite direction. The speed is determined by the difference in value from 90°; 0° or 180° will turn the motor at its maximum speed while 91° or 89° at its minimum rate; | ||
+ | * **linear servomotor** – with the help of additional transfers it allows moving forward or backward; it doesn’t rotate. | ||
+ | |||
+ | Unfortunately, | ||
+ | |||
+ | <figure label> | ||
+ | {{ : | ||
+ | < | ||
+ | </ | ||
+ | |||
+ | <figure label> | ||
+ | {{ : | ||
+ | < | ||
+ | </ | ||
+ | |||
+ | The example code: | ||
+ | <code c> | ||
+ | #include < | ||
+ | Servo servo; //Define a Servo object | ||
+ | |||
+ | void setup () | ||
+ | { | ||
+ | servo.attach(6); | ||
+ | servoLeft.write(90); | ||
+ | Serial.begin(9600); | ||
+ | } | ||
+ | |||
+ | void loop () | ||
+ | { | ||
+ | servoLeft.write(110); | ||
+ | delay(200); //wait for 200 ms | ||
+ | servoLeft.write(70);// | ||
+ | delay(200); //Wait for 200 ms | ||
+ | } | ||
+ | |||
+ | </ | ||
+ | |||
+ | ==== ==== | ||
+ | <box # | ||
+ | <box # | ||
+ | ==== IoT Application Example Projects ==== | ||
+ | <box # | ||
+ | <box # | ||
+ | |||
+ | Many IoT projects developed using an Arduino board can be found in the official Arduino Project Hub ((https:// | ||
+ | |||
+ | |||
+ | One of the IoT projects available at the Arduino Project Hub is the **Arduino Home Controller Activated by Alexa** ((https:// | ||
+ | |||
+ | |||
+ | The ** Home Security Model** ((https:// | ||
+ | |||
+ | |||
+ | The project **Plant Monitoring System uses AWS IoT** ((https:// | ||
+ | |||
+ | Here is another IoT project about the home automation system, called **Arduino based Amazon Echo using 1Sheeld** | ||
+ | ((https:// | ||
+ | |||
+ | |||
+ | Few of the Arduino IoT related projects are also provided on the hackster.io website ((https:// | ||
+ | |||
+ | The first project that is viewed is the **Harry Potter Weasleys' | ||
+ | |||
+ | |||
+ | |||
+ | |||
+ | |||
+ | |||
+ | |||
+ | |||
+ | ==== ==== | ||
+ | <box # | ||
+ | <box # | ||
+ | ==== Setting Up Development/ | ||
+ | <box # | ||
+ | <box # | ||
+ | |||
+ | === Using Breadboard === | ||
+ | The breadboard is a mechanical base for electronics prototyping. Originally for this purpose was used the wooden board for cutting bread, that is why the name used now is the " | ||
+ | |||
+ | <figure label> | ||
+ | {{ : | ||
+ | < | ||
+ | </ | ||
+ | |||
+ | On the front surface of the breadboard, many small holes are connected on the back of the board in a specific pattern using metal clips. These clips hold component leg or wire in place when they are put into the hole. | ||
+ | |||
+ | As the example, the circuit that contains the LED and resistance is taken. | ||
+ | |||
+ | <figure label> | ||
+ | {{ : | ||
+ | < | ||
+ | </ | ||
+ | |||
+ | Following the schematics, all the necessary components are connected in the right way using the breadboard. | ||
+ | |||
+ | <figure label> | ||
+ | {{ : | ||
+ | < | ||
+ | </ | ||
+ | |||
+ | Two side columns of the breadboard are made easily accessible from the rest of the breadboard and are commonly used for connecting the power to the circuit. Almost any DC (direct current) power source can be used to power the circuit, like batteries, Arduino board power pins, AC/DC regulators etc. | ||
+ | |||
+ | Two columns of 5 hole rows are used for connecting components. Extra connections can be made using wires. The gap in the middle allows using DIP (dual in-line package) circuits. | ||
+ | |||
+ | More information on breadboards can be found in the SparkFun webpage ((https:// | ||
+ | |||
+ | |||
+ | === Soldering === | ||
+ | |||
+ | Soldering is one of the essential skills in the world of electronics. The basic of electronics can also be a learner without the knowledge of how to solder; however, the soldering allows to work on more exciting projects and to join a wide range of electronics enthusiasts. This skill is essential because nowadays the electronic and electrical equipment is being used more often. The essential element of the knowledge about electronics is not only the ability to understand the working principles of the electronics but also the skill to build, repair and supplement the electronic devices. | ||
+ | \\ | ||
+ | \\ | ||
+ | \\ | ||
+ | **Materials** | ||
+ | |||
+ | The main soldering material is a **solder**. As the name of the material indicates, it is a compound of various soft metals and consumable materials, which is usually similar to a wire, wrapped in a reel or other easy-to-use packaging. | ||
+ | |||
+ | <figure label> | ||
+ | {{ : | ||
+ | < | ||
+ | </ | ||
+ | |||
+ | Different types of solder vary in **diameter** of the wire and the **chemical composition**. The type of solder that is used depends on the task. | ||
+ | |||
+ | According to the chemical composition, | ||
+ | |||
+ | Since 2006, many countries have forbidden using lead-containing solder, caring for the protection of nature and human health. When lead accumulates in the human body in significant amounts, it can cause poisoning. For this reason, it is important to remember – after using lead-containing solder, you should **carefully wash your hands**. | ||
+ | |||
+ | To avoid the risk of getting lead in the human body, the alternative is to use lead-free solder. Nevertheless few things need to be taken into account – the melting temperature of lead-free solder is higher and grip with other materials is lower. For improving the grip, flux can be used. Some solders already have flux in the core of the wire, so it is not necessary to buy them separately. | ||
+ | |||
+ | The diameter of the solder wire depends on the size of details that need to be soldered. The bigger the detail, the bigger the diameter of the solder wire. | ||
+ | |||
+ | **Tools** | ||
+ | |||
+ | Tools used for soldering are a soldering iron, stand for soldering iron, as well as different tools for removing solder and keeping parts together. | ||
+ | |||
+ | A **soldering iron** is an electrical heater that is used for heating the solder to it's melting temperature. As with all of the electrical devices, the instructions provided by the manufacturer should be followed when using the soldering iron. For specific tasks, there are also hot air and gas soldering irons. In this section, only the electric ones will be described. | ||
+ | |||
+ | There are different types of soldering irons so that they can be effectively used for diverse tasks. Soldering irons can vary in a shape of the tip, electrical capacity, heating temperature and control options. However, the primary indicator is the convenience of use. If the chosen soldering iron is too big, it will be difficult to solder small details. If it is too small, details probably will not get enough of the heat, and the solder will not stick properly to them. For beginners, it is advisable to use a soldering iron with a conical tip. | ||
+ | |||
+ | <figure label> | ||
+ | {{ : | ||
+ | < | ||
+ | </ | ||
+ | |||
+ | In addition to the soldering iron, there are several useful tools for soldering. | ||
+ | * **Solder wick** – used for desoldering, | ||
+ | |||
+ | <figure label> | ||
+ | {{ : | ||
+ | < | ||
+ | </ | ||
+ | |||
+ | * **Solder vacuum** – used for desoldering, | ||
+ | |||
+ | <figure label> | ||
+ | {{ : | ||
+ | < | ||
+ | </ | ||
+ | |||
+ | * ** Third-hand** – a holder of details or other parts. It is especially useful for beginners. | ||
+ | |||
+ | <figure label> | ||
+ | {{ : | ||
+ | < | ||
+ | </ | ||
+ | |||
+ | |||
+ | **Process of Soldering** | ||
+ | |||
+ | It is not easy to describe the process of soldering in words, because it is connected with the kinesthetic skills of people and the paid attention. However, it is essential to follow several pieces of advice for good soldering. | ||
+ | |||
+ | - Be careful with the hot soldering iron! | ||
+ | - The working place should always be clean; it is advisable not to take a meal at the working place (because of the poisonous nature of the lead in the solder). | ||
+ | - It is advisable to use the third hand when it is possible. | ||
+ | - If possible, the temperature of the soldering iron should always be around 350 °C. | ||
+ | - If there is smoke coming from the soldering iron, the temperature should be decreased, or it should be turned off completely. | ||
+ | - Before soldering, a special soldering iron cleaner (wet sponge or special paste for cleaning the tip) should be used. | ||
+ | - The side of the soldering iron tip should be used when soldering rather than the very tip of it. | ||
+ | - The good contact can be ensured when heating simultaneously both components that are soldered. | ||
+ | - When the detail has been soldered, first the solder wire should be taken off and only then – the soldering iron. | ||
+ | - Good soldering of the detail with the board looks like a tip of the volcano rather than a ball or messy pile of solder. | ||
+ | |||
+ | In the Figure {{ref> | ||
+ | |||
+ | <figure label1> | ||
+ | {{ : | ||
+ | < | ||
+ | </ | ||
+ | |||
+ | |||
+ | |||
+ | ==== ==== | ||
+ | <box # | ||
+ | <box # | ||
+ | ==== Arduino Programming Fundamentals ==== | ||
+ | <box # | ||
+ | <box # | ||
+ | |||
+ | The following sub-chapters cover programming fundamentals in Arduino(C) C/C++, which complies with the most C/C++ notations and have some specific Arduino notations. | ||
+ | Those who feel comfortable in programming will find these chapter somewhat introductory, | ||
+ | |||
+ | * " | ||
+ | |||
+ | * " | ||
+ | |||
+ | * " | ||
+ | |||
+ | * " | ||
+ | |||
+ | * " | ||
+ | |||
+ | * " | ||
+ | |||
+ | * " | ||
+ | |||
+ | * " | ||
+ | |||
+ | <note tip>This manual refers to the particular version of the software (here Arduino IDE and related toolkits) available at the moment of writing of this book, thus accessing specific features may change over time along with the evolution of the platform. Please refer attached documentation (if any) and browse Internet resources to find lates guidances on how to configure development platform, when in doubt.</ | ||
+ | |||
+ | |||
+ | |||
+ | |||
+ | === === | ||
+ | <box # | ||
+ | <box # | ||
+ | === Setting Up the Programming Environment === | ||
+ | <box # | ||
+ | <box # | ||
+ | |||
+ | Before starting programming the microcontroller, | ||
+ | |||
+ | == Connection == | ||
+ | **Arduino Uno** microcontroller is taken as a board for programming example tasks. It can be connected to a computer, using **Universal Serial Bus** (USB) port, using the appropriate USB cable. A microcontroller can be used together with a prototyping board or a robot. In the simplest programming tasks, it can be used as an independent device. | ||
+ | |||
+ | |||
+ | == Power == | ||
+ | The microcontroller has to be powered via an external power supply or USB port. The microcontroller determines the power source automatically. If external power supplies other than USB are used, GND and VIN ports should be used to connect the power supply. The manufacturer recommends the use of a voltage of 7–12 V to ensure a normal operation of the microcontroller. If the voltage is exceeded, before reaching 20 V, then the power supply circuits of the microcontroller may get overheated. If the supply voltage is lower than 7 V, then the microcontroller may function unstable, and the result will be unpredictable. | ||
+ | |||
+ | In addition to the above mentioned, the microcontroller can provide a small power supply for external circuits by connecting them according to the microcontroller pins. | ||
+ | |||
+ | <table PowerPins> | ||
+ | < | ||
+ | ^ Pin ^ Description | ||
+ | | VIN | The input of a power supply when a USB port is not used, i.e., an external power supply is used | | ||
+ | | 5V | A regulated 5 V power supply, which can be provided via both USB and VIN | | ||
+ | | 3.3V | A 3.3 V supply voltage for external circuits. The maximum current that this output can provide is 50 mA. If it is exceeded, the power supply circuits of the microcontroller may be permanently damaged | | ||
+ | | GND | Ground or port 0 | | ||
+ | </ | ||
+ | |||
+ | |||
+ | == Inputs/ | ||
+ | Each of the 14 digital inputs/ | ||
+ | |||
+ | Descriptions of other microcontroller pin and their specific use are explained below. | ||
+ | In addition to these I/O, the microcontroller also provides other specific functions that will be described below. | ||
+ | |||
+ | <table I/OPins> | ||
+ | < | ||
+ | ^ Pin ^ Description | ||
+ | | 0(RX) and 1(TX) | **Serial I/O** for serial communication. RX is used for receiving data, and TX for sending data to external devices. For data transmitting and receiving, the voltage must not exceed 5 V | | ||
+ | | 2 and 3 | **External interrupt** pins that can be used to receive an external interrupt in cases when the value is low, the value is changed, etc. For this functionality the function // | ||
+ | | PWM: 3, 5, 6, 9, 10, 11 | **Pulse Width Modulation (PWM)** pins are used to provide 8-bit PWM signal that often can be used for motor control or other specific use cases. For this functionality the // | ||
+ | | SPI: 10(SS), 11(MOSI), 12(MISO), 13(SCK) | ||
+ | | LED: 13 | This pin is used to manage the built-in LED. LED can be turned on by setting the value of pin HIGH and turned off by setting pin value //LOW// | | ||
+ | | A4(SDA) and A5(SCL) | ||
+ | | AREF | It is the reference voltage for the analogue inputs. For this functionality // | ||
+ | | Reset | Gives the opportunity to reset the microcontroller by setting this pin to //LOW// | | ||
+ | </ | ||
+ | |||
+ | == Installing the Programming Environment == | ||
+ | To start the development of software for a microcontroller, | ||
+ | |||
+ | **Step 1. Preparing Arduino UNO and the USB Cable** | ||
+ | |||
+ | Before installing the programming environment, | ||
+ | |||
+ | <figure label> | ||
+ | {{ : | ||
+ | < | ||
+ | </ | ||
+ | |||
+ | |||
+ | |||
+ | <figure label> | ||
+ | {{ : | ||
+ | < | ||
+ | </ | ||
+ | |||
+ | **Step 2. Downloading the Arduino Software Development Environment** | ||
+ | |||
+ | The open-source Arduino Software (Integrated development environment (IDE)) can be found in the official Arduino website ((https:// | ||
+ | |||
+ | <figure label> | ||
+ | {{ : | ||
+ | < | ||
+ | </ | ||
+ | |||
+ | For Windows OS, the Windows Installer should be clicked, and then the file should be saved on the computer. When the installation file has downloaded, the file should be run. If the ZIP file was downloaded, it is necessary to unarchive it and to run the installer. Follow the instructions of the installer. If the operating system asks for permission to install the driver of the board – allow it. | ||
+ | |||
+ | It is also possible to use Arduino Web Editor (can be found on the same website) to work online with the Arduino board, but this option will not be considered in this manual. | ||
+ | |||
+ | <figure label> | ||
+ | {{ : | ||
+ | < | ||
+ | </ | ||
+ | |||
+ | **Step 3. Connecting to Arduino** | ||
+ | |||
+ | Using USB cable, Arduino needs to be connected to a free USB port of a computer. The blue LED on the Arduino board starts to shine continuously. Aforementioned is the indicator that the Arduino board is working. | ||
+ | |||
+ | The green LED will blink, and that will indicate the performance of the manufacturer test software. In case if the green LED is not flashing, it is not an error. | ||
+ | |||
+ | **Step 4. Starting Up the Programming Environment** | ||
+ | |||
+ | The Arduino programming environment can be started with the double-click on the desktop shortcut of the Arduino software. The language of the environment will respond to the one that is set up in the OS of the computer, that means if it is English, then the menu of the programming environment will also be in the English language. To change the language preferences, | ||
+ | |||
+ | **Step 5. Open the Example Program** | ||
+ | |||
+ | In the Arduino IDE open //File -> Examples -> 01.Basics -> Blink// as shown in the image below. | ||
+ | <figure label> | ||
+ | {{ : | ||
+ | < | ||
+ | </ | ||
+ | |||
+ | This will open in the new window an example program for turning on and off green LED that is situated on the Arduino UNO board with the 1 second delay. | ||
+ | <figure label> | ||
+ | {{ : | ||
+ | < | ||
+ | </ | ||
+ | |||
+ | **Step 6. Choosing the Microcontroller** | ||
+ | |||
+ | In this step it is necessary to choose the type of board that is used. In this example the Arduino UNO board is used that is why in the menu of Arduino IDE choose //Tools -> Board -> Arduino/ | ||
+ | <figure label> | ||
+ | {{ : | ||
+ | < | ||
+ | </ | ||
+ | |||
+ | **Step 7. Setting Up COM Port** | ||
+ | |||
+ | To ensure transmitting and receiving data to/from the microcontroller, | ||
+ | |||
+ | <figure label> | ||
+ | {{ : | ||
+ | < | ||
+ | </ | ||
+ | |||
+ | **Step 8. Uploading the Example Program to the Board** | ||
+ | |||
+ | Now the program can be uploaded to the Arduino board using the Upload button in the top left corner of the software, then wait for a few seconds, during which you can see the data sending indicators – LEDs are blinking fast (indicates sending or receiving data) – and wait for the message to be " | ||
+ | |||
+ | <figure label> | ||
+ | {{ : | ||
+ | < | ||
+ | </ | ||
+ | |||
+ | After a few seconds, the green LED will blink with a one-second interval like it is written in the source code. If this can be observed successfully, | ||
+ | |||
+ | In case if the blinking green LED cannot be observed, instructions for troubleshooting can be read in the following link ((http:// | ||
+ | |||
+ | If you want to get acquainted yourself with microcontroller capabilities or programming basics independently, | ||
+ | * examples for the accomplishing tasks of different level of difficulty ((http:// | ||
+ | * reference for the programming language used ((http:// | ||
+ | |||
+ | **Check Yourself** | ||
+ | |||
+ | 1. What power supply Arduino UNO microcontroller requires? | ||
+ | |||
+ | 2. How to operate with inputs/ | ||
+ | |||
+ | 3. Try different examples in the menu of Arduino IDE. | ||
+ | === === | ||
+ | <box # | ||
+ | <box # | ||
+ | === The Syntax and the Structure of the Program === | ||
+ | <box # | ||
+ | <box # | ||
+ | |||
+ | == Syntax == | ||
+ | Arduino IDE is a software that allows writing Arduino code. Each file with Arduino code is called **a sketch**. The Arduino programming language is similar to the C++ language. For the Arduino IDE to compile the written code without errors, it is important to follow the pre-defined syntax. | ||
+ | |||
+ | **Define** | ||
+ | |||
+ | //#define// is a component that allows giving a name to a constant value at the very beginning of the program. | ||
+ | |||
+ | <code c> | ||
+ | #define constant 4 | ||
+ | </ | ||
+ | |||
+ | In this example, the value four is assigned to the // | ||
+ | |||
+ | Note that at the end of this expression semicolon (;) is not necessary and between the name and the value, the sign of equality (=) should not be added! | ||
+ | |||
+ | **Include** | ||
+ | |||
+ | //# | ||
+ | |||
+ | <code c> | ||
+ | #include < | ||
+ | </ | ||
+ | |||
+ | In this example, the library called Servo.h that manages servomotors has been added to the sketch. | ||
+ | |||
+ | **Comments** | ||
+ | |||
+ | There are two ways to write comments in the sketch so that the written text is not compiled as a part of the running code. | ||
+ | |||
+ | <code c> | ||
+ | //Single line comment is written here | ||
+ | </ | ||
+ | |||
+ | The double backslash is used when the only single line should be commented on. | ||
+ | |||
+ | <code c> | ||
+ | / | ||
+ | Second line of the comment | ||
+ | ... | ||
+ | */ | ||
+ | </ | ||
+ | |||
+ | In this way, the backslash followed by asterisk defines the beginning of the block comment, and the asterisk followed by backslash defines the end of the block comment. | ||
+ | |||
+ | **Semicolon** | ||
+ | |||
+ | The semicolon (//;//) is used at the end of each statement of the code. | ||
+ | |||
+ | <code c> | ||
+ | int pin = 5; | ||
+ | </ | ||
+ | |||
+ | In this example, a single statement is //int pin = 5// and the semicolon at the end tells the compiler that this is the end of the statement and it can continue with the next one. | ||
+ | |||
+ | **Curly Braces** | ||
+ | |||
+ | Curly braces are used to enclose a further block of instructions. Curly braces usually follow different functions that will be viewed in the further sections. | ||
+ | |||
+ | Each opening curly brace should always be by a closing curly brace. Otherwise, the compiler will show an error. | ||
+ | |||
+ | <code c> | ||
+ | void function(datatype argument){ | ||
+ | statements(s) | ||
+ | } | ||
+ | </ | ||
+ | Use of curly braces in the own defined function. | ||
+ | |||
+ | |||
+ | == Structure of the Program == | ||
+ | Below is given an example, how a new empty sketch looks like. | ||
+ | |||
+ | <figure label> | ||
+ | {{ : | ||
+ | < | ||
+ | </ | ||
+ | |||
+ | Each Arduino sketch contains multiple parts. | ||
+ | - Global definition section – the section where variables and constants are defined that the working range is in the whole sketch that means both in the initialisation and the loop sections. This section is at the very beginning of the sketch, before the setup function. | ||
+ | - Initialisation section – is executed only once before running the basic program. In this part usually, all variables, I/O of the board pins, constants, are defined, etc. The most essential is to define all inputs and outputs that will be used in the program that defines how each pin will be used.\\ \\ The construction of the setup function: <code c> | ||
+ | void setup() | ||
+ | { //Beginning of the initialization function | ||
+ | //The body of the function - contains all executable statements | ||
+ | } //The end of the initialization function | ||
+ | |||
+ | </ | ||
+ | - Loop section – the part that is executed continuously, | ||
+ | void loop() | ||
+ | { // | ||
+ | // | ||
+ | } //The end of the loop function | ||
+ | |||
+ | </ | ||
+ | The result data type of this function is the same as previous – //void// – that shows that the function does not have the result, it will be executed in the loop continuously while the program is working. | ||
+ | |||
+ | |||
+ | |||
+ | == Blink LED == | ||
+ | The code of the Blink LED program code will be viewed now. The example can be opened by following the path in Arduino IDE: //File -> Examples -> 01.Basics -> Blink//. | ||
+ | |||
+ | <figure label> | ||
+ | {{ : | ||
+ | < | ||
+ | </ | ||
+ | |||
+ | When the Blink LED example program is opened, the following sketch should open in the programming environment: | ||
+ | |||
+ | <figure label> | ||
+ | {{ : | ||
+ | < | ||
+ | </ | ||
+ | |||
+ | The code of the example program is the following: | ||
+ | <code c> | ||
+ | //The setup function runs once when you press reset or power the board | ||
+ | void setup() { | ||
+ | // | ||
+ | // | ||
+ | pinMode(LED_BUILTIN, | ||
+ | } | ||
+ | |||
+ | //The loop function runs over and over again forever | ||
+ | void loop() { | ||
+ | digitalWrite(LED_BUILTIN, | ||
+ | delay(1000); | ||
+ | digitalWrite(LED_BUILTIN, | ||
+ | delay(1000); | ||
+ | } | ||
+ | </ | ||
+ | |||
+ | In the source code of the program, the following things can be seen. | ||
+ | - It defined that the LED_BUILTIN is set to be the output of the program. In this example sketch, the output periodically sends the specific signal that is in the level of the logical 1 (+5 V) and 0 (0 V). Sending the output signal to the built-in LED: the LED is periodically turned on and off. | ||
+ | - Continuous executable function //loop()// is created that allocates 1 second (1000 ms) of time to each level of signal. It is done by pausing the execution of the program. While the program is not changing the states of the inputs/ | ||
+ | - The last row indicates that the program will be paused for a 1 second also when the output level is set to be 0 V. In this way, the period of LED on and off are equal. After executing this program, the program returns to the first line of the //loop()// function, and the execution starts from the beginning. | ||
+ | |||
+ | |||
+ | == Hello World == | ||
+ | Hello World program is the simplest program because it simply outputs the text to the screen. | ||
+ | Here is the Hello World program for Arduino that outputs the text on the Serial Monitor each second: | ||
+ | <code c> | ||
+ | void setup() { | ||
+ | Serial.begin(9600); | ||
+ | } | ||
+ | |||
+ | void loop() { | ||
+ | Serial.println(" | ||
+ | delay(1000); | ||
+ | } | ||
+ | </ | ||
+ | |||
+ | Serial Monitor can be found following the path: //Tools -> Serial Monitor//. | ||
+ | |||
+ | In the code can be seen that the //setup()// function contains the following command: | ||
+ | <code c> | ||
+ | Serial.begin(9600); | ||
+ | </ | ||
+ | This statement opens the serial port at the initialisation of the program so that the Serial Monitor can be used for outputting text or values on the screen. | ||
+ | |||
+ | For printing out text the following command is used: | ||
+ | <code c> | ||
+ | Serial.println(" | ||
+ | </ | ||
+ | |||
+ | **Check Yourself** | ||
+ | |||
+ | 1. How to attach any library to a sketch? | ||
+ | |||
+ | 2. What command are expressions not usually separated by the semicolon? | ||
+ | |||
+ | 3. How to establish serial communication between devices? | ||
+ | |||
+ | 4. How does //delay()// command works? | ||
+ | |||
+ | * Stops LED blinking specified number of milliseconds. | ||
+ | |||
+ | * Stops program execution for a specified number of seconds. | ||
+ | |||
+ | * Stops program execution for a specified number of milliseconds. | ||
+ | === === | ||
+ | <box # | ||
+ | <box # | ||
+ | === Data Types and Variables === | ||
+ | <box # | ||
+ | <box # | ||
+ | |||
+ | |||
+ | == Data Types == | ||
+ | Each variable has its data type that determines its place in the memory of the microcontroller and also the way how it can be used. There are plenty of different data types. Further will be viewed the most used ones. | ||
+ | * **// | ||
+ | |||
+ | <code c> | ||
+ | byte exampleVariable = 123; | ||
+ | </ | ||
+ | |||
+ | * **//int//** – the whole number of 16 bits that can contain values from –32 767 to 32 768. | ||
+ | |||
+ | <code c> | ||
+ | int exampleVariable = 12300; | ||
+ | </ | ||
+ | |||
+ | * **// | ||
+ | |||
+ | <code c> | ||
+ | float exampleVariable = 12300.546; | ||
+ | </ | ||
+ | |||
+ | * **// | ||
+ | |||
+ | <code c> | ||
+ | int firstArray[] = {12, | ||
+ | </ | ||
+ | |||
+ | Square brackets of the array can be used to access some value in the array by index. In the following example, the element with index 1 (that is –3) is assigned to the // | ||
+ | |||
+ | <code c> | ||
+ | int secondVariable = firstArray[1]; | ||
+ | </ | ||
+ | |||
+ | An array can be easily processed in the cycle. The next example shows how to store the necessary values automatically from the analogue signal input to the previously defined array. | ||
+ | |||
+ | <code c> | ||
+ | //The cycle that repeats 4 times | ||
+ | for(int i = 0; i < 4; i = i + 1){ | ||
+ | // | ||
+ | | ||
+ | } | ||
+ | |||
+ | </ | ||
+ | |||
+ | This cycle in the example starts with index 0 (//i// = 0), and it increases by 1 while it is smaller than 4 (not including). That means in the last cycle the index value will be 3, because when the //i// equals 4, the inequality //i// < 4 is not true, and the cycle stops working. | ||
+ | |||
+ | * **// | ||
+ | |||
+ | |||
+ | |||
+ | |||
+ | == Data Type Conversion == | ||
+ | Data type conversion can be done using multiple techniques – casting or data type conversion using specific functions. | ||
+ | |||
+ | * **Casting** – cast operator translates one data type into another straightforward. The desired type of variable should be written in the brackets before the variable data type of which needs to be changed. In the following example, where the variable type is changed from float to int, the value is not rounded but truncated. Casting can be done to any variable type. | ||
+ | |||
+ | <code c> | ||
+ | int i; | ||
+ | float f=4.7; | ||
+ | |||
+ | i = (int) f; //Now i is 4 | ||
+ | </ | ||
+ | |||
+ | * **Converting** – //byte(), char(), int(), long(), word(), float()// functions are used to convert any type of variable to the specified data type. | ||
+ | |||
+ | <code c> | ||
+ | int i = int(123.45); | ||
+ | </ | ||
+ | |||
+ | * **Converting //String// to //float//** – function // | ||
+ | |||
+ | <code c> | ||
+ | String string = " | ||
+ | float f = string.toFLoat(); | ||
+ | </ | ||
+ | |||
+ | * **Converting //String// to //Int//** – function //toInt()// converts //String// type of variable to the //Int//. In the following example is shown the use of this function. | ||
+ | |||
+ | <code c> | ||
+ | String string = " | ||
+ | int i = string.toInt(); | ||
+ | </ | ||
+ | |||
+ | |||
+ | == Arithmetic Operators == | ||
+ | Arithmetic operations on Arduino are used to do mathematical calculations with the numbers or numerical variables. The arithmetic operators are the following. | ||
+ | * **Addition (+)** – one of the four primary arithmetic operations that are used to add numbers. Addition operator can be used to add only numbers, only numeric variables or the mix of both. The following example shows the use of the addition operator. | ||
+ | <code c> | ||
+ | int result = 1 + 2; //The result of the addition operation will be 3 | ||
+ | </ | ||
+ | * **Subtraction (-)** – the operation that subtracts one number from another where result is the difference between these numbers. | ||
+ | <code c> | ||
+ | int result = 3 - 2; //The result of the subtraction operation will be 1 | ||
+ | </ | ||
+ | * **Multiplication (*)** – the operation that multiplies numbers and gives the result. | ||
+ | <code c> | ||
+ | int result = 2 * 3; //The result of the multiplication operation will be 6 | ||
+ | </ | ||
+ | * **Division (/)** – the operation that divides one number by another. If the result variable has the //integer// type, the result will always be the whole part of the division result without the fraction behind it. If the precise division is necessary, it is important to use //float// type of variable for this purpose. | ||
+ | <code c> | ||
+ | //The result of the division operation will be 3 | ||
+ | //(Only the whole part of the division result) | ||
+ | int result = 7 / 2; | ||
+ | //The result of the division operation will be 3.5 | ||
+ | float result2 = 7.0 / 2.0; | ||
+ | </ | ||
+ | * **Modulo (%)** – the operation that finds the remainder of the division of two numbers. | ||
+ | <code c> | ||
+ | //The result of the modulo operation will be 1, | ||
+ | //Because if 7 is divided by 3, the remaining is 1 | ||
+ | int result = 7 % 3; | ||
+ | </ | ||
+ | * **Assignment operator (=)** – the operator that assigns the value on the right to the variable that is on the left of the assignment operator. The work of an assignment operator can be seen in any of the previously viewed operation examples. | ||
+ | |||
+ | |||
+ | == Compound Operators == | ||
+ | Compound operators in Arduino are a short way of writing down the arithmetic operations with variables. All of these operations are done on integer variables. These operands are often used in the loops when it is necessary to manipulate with the same variable in each iteration of the cycle. The compound operators are the following. | ||
+ | * **Increment (++)** – increases the value of integer variable by one. | ||
+ | <code c> | ||
+ | int a = 5; | ||
+ | a++; //The operation a = a + 1; the result will be 6 | ||
+ | </ | ||
+ | * **Decrement (- -)** – decreases the value of integer variable by one. | ||
+ | <code c> | ||
+ | int a = 5; | ||
+ | a--; //The operation a = a – 1; the result will be 4 | ||
+ | </ | ||
+ | * **Compound addition (+=)** – adds the right operand to the left operand and assigns the result to the left operand. | ||
+ | <code c> | ||
+ | int a = 5; | ||
+ | a+=2; //The operation a = a + 2; the result will be 7 | ||
+ | </ | ||
+ | * **Compound subtraction (-=)** – subtracts the right operand from the left operand and assigns the result to the left operand. | ||
+ | <code c> | ||
+ | int a = 5; | ||
+ | a-+3; //The operation a = a – 3; the result will be 2 | ||
+ | </ | ||
+ | * **Compound multiplication (*=)** – multiplies the left operand by the right operand and assigns the result to the left operand. | ||
+ | <code c> | ||
+ | int a = 5; | ||
+ | a*=3; //The operation a = a × 3; the result will be 15 | ||
+ | </ | ||
+ | * **Compound division (/=)** – divides the left operand with the right operand and assigns the result to the left operand. | ||
+ | <code c> | ||
+ | int a = 6; | ||
+ | a/=3; //The operation a = a / 3; the result will be 2 | ||
+ | </ | ||
+ | * **Compound modulo (%=)** – takes modulus using two operands and assigns the result to the left operand. | ||
+ | <code c> | ||
+ | int a = 5; | ||
+ | //The result will be the remaining | ||
+ | //Part of the operation a/2; it results in 1 | ||
+ | a%=2; | ||
+ | </ | ||
+ | * **Compound bitwise //OR// (|=)** – bitwise //OR// operator that assigns the value to the operand on the left. | ||
+ | <code c> | ||
+ | int a = 5; | ||
+ | a|=2; //The operation a=a|2; the result will be 7 | ||
+ | </ | ||
+ | * **Compound bitwise //AND// (&=)** – bitwise //AND// operator that assigns the value to the operand on the left. | ||
+ | <code c> | ||
+ | int a = 6; | ||
+ | a&=; //The operation a=a&2; the result will be 2 | ||
+ | </ | ||
+ | |||
+ | |||
+ | **Check Yourself** | ||
+ | |||
+ | 1. What is the data type used for a variable range 0...255? | ||
+ | |||
+ | 2. What should data type be used for more precise measurements? | ||
+ | |||
+ | 3. Make data type conversion char to string. | ||
+ | |||
+ | 4. What is the main advantage of using compound operators? | ||
+ | === === | ||
+ | <box # | ||
+ | <box # | ||
+ | === Program Control Structures === | ||
+ | <box # | ||
+ | <box # | ||
+ | |||
+ | == Control Structure == | ||
+ | //**if**// is a statement that checks the condition and executes the following statements if the condition is //TRUE//. There are multiple ways how to write down the //if// statement: | ||
+ | |||
+ | <code c> | ||
+ | //1st example | ||
+ | if (condition) statement; | ||
+ | |||
+ | //2nd example | ||
+ | if (condition) | ||
+ | statement; | ||
+ | |||
+ | //3rd example | ||
+ | if (condition) { statement; } | ||
+ | |||
+ | //4th example | ||
+ | if (condition) | ||
+ | { | ||
+ | statement; | ||
+ | } | ||
+ | </ | ||
+ | |||
+ | When both //TRUE// and //FALSE// cases of the condition should be viewed, the // | ||
+ | |||
+ | <code c> | ||
+ | if (condition) { | ||
+ | statement1; | ||
+ | } | ||
+ | else { | ||
+ | statement2; | ||
+ | } | ||
+ | </ | ||
+ | |||
+ | If more conditions should be viewed, the //**else if**// part is added to the //if// statement: | ||
+ | <code c> | ||
+ | if (condition1) { | ||
+ | statement1; | ||
+ | } | ||
+ | else if (condition2) { | ||
+ | statement2; | ||
+ | } | ||
+ | else { | ||
+ | statement3; | ||
+ | } | ||
+ | </ | ||
+ | |||
+ | The example when the //x// variable is compared and in the cases when it is higher than 10, the // | ||
+ | <code c> | ||
+ | if (x> | ||
+ | { | ||
+ | //Statement is executed if the x > 10 expression is true | ||
+ | digitalWrite(LEDpin, | ||
+ | } | ||
+ | </ | ||
+ | |||
+ | |||
+ | == Logical Operators == | ||
+ | Logical operators are widely used together with the condition operator //if// that is described below. | ||
+ | |||
+ | **Comparison Operators** | ||
+ | |||
+ | There are multiple comparison operators used for comparing variables and values. All of these operators compare the value of the variable on the left to the value of the variable on the right. Comparison operators are the following: | ||
+ | * == (equal to) – if they are equal, the result is //TRUE//, otherwise //FALSE//; | ||
+ | * != (not equal to) – if they are not equal, the result is //TRUE//, otherwise //FALSE//; | ||
+ | * < (less than) – if the value of the variable on the left is less than the value of the variable on the right, the result is //TRUE//, otherwise //FALSE//; | ||
+ | * < = (less than or equal to) – if the value of the variable on the left is less than or equal to the value of the variable on the right, the result is //TRUE//, otherwise //FALSE//; | ||
+ | * > (greater than) – if the value of the variable on the left is greater than the value of the variable on the right, the result is //TRUE//, otherwise //FALSE//; | ||
+ | * > = (greater than or equal to) – if the value of the variable on the left is greater than or equal to the value of the variable on the right, the result is //TRUE//, otherwise //FALSE//. | ||
+ | |||
+ | Examples: | ||
+ | <code c> | ||
+ | if (x==y){ //Equal | ||
+ | //Statement | ||
+ | } | ||
+ | |||
+ | if (x!=y){ //Not equal | ||
+ | //Statement | ||
+ | } | ||
+ | |||
+ | if (x<y){ //Less than | ||
+ | //Statement | ||
+ | } | ||
+ | |||
+ | if (x<=y){ //Less than or equal | ||
+ | //statement | ||
+ | } | ||
+ | |||
+ | if (x>y){ //Greater than | ||
+ | //Statement | ||
+ | } | ||
+ | |||
+ | if (x>=y){ //Greater than or equal | ||
+ | //Statement | ||
+ | } | ||
+ | </ | ||
+ | |||
+ | **Boolean Operators** | ||
+ | |||
+ | Three Boolean logical operators in the Arduino environment are the following: | ||
+ | * ! (logical //NOT//) – reverses the logical state of the operand. If a condition is //TRUE// the logical NOT operator will turn it to //FALSE// and the other way around; | ||
+ | * && (logical //AND//) – the result is //TRUE// when both operands on the left and on the right of the operator are //TRUE//. If even one of them is //FALSE// the result is //FALSE//; | ||
+ | * || (logical //OR//) – the result is //TRUE// when at least one of the operands on the left and on the right of the operator is //TRUE//. If both of them are //FALSE// the result is //FALSE//. | ||
+ | |||
+ | Examples: | ||
+ | <code c> | ||
+ | //Logical NOT | ||
+ | if (!a) { //The statement inside if will execute when the a is FALSE | ||
+ | b = !a; //The reverse logical value of a is assigned to the variable b | ||
+ | } | ||
+ | |||
+ | //Logical AND | ||
+ | //The statement inside if will execute when the | ||
+ | //Values both of the a and b are TRUE | ||
+ | if (a && b){ | ||
+ | //Statement | ||
+ | } | ||
+ | |||
+ | //Logical OR | ||
+ | //The statement inside if will execute when at least one of the | ||
+ | //a and b values is TRUE | ||
+ | if (a || b){ | ||
+ | //Statement | ||
+ | } | ||
+ | </ | ||
+ | |||
+ | == Switch Case Statement == | ||
+ | Switch statement similar like //if// statement controls the flow of program. The code inside //switch// is executed in various conditions. A //switch// statement compares the values of a variable to the specified values in the //case// statements. Allowed data types of the variable are //int// and //char//. The //break// keyword exits the //switch// statement. | ||
+ | |||
+ | Examples: | ||
+ | <code c> | ||
+ | switch (x) { | ||
+ | case 0: //Executes when the value of x is 0 | ||
+ | // statements | ||
+ | | ||
+ | |||
+ | case 1: //Executes when the value of x is 1 | ||
+ | // statements | ||
+ | | ||
+ | |||
+ | | ||
+ | // statements | ||
+ | | ||
+ | } | ||
+ | </ | ||
+ | |||
+ | |||
+ | **Check Yourself** | ||
+ | |||
+ | 1. Which code part is the correct one? | ||
+ | |||
+ | * if(value == 1) digitalWrite(13, | ||
+ | * if (value == 1); digitalWrite(13, | ||
+ | * if (value == 1) DigitalRead(13, | ||
+ | 2. What is the output of the next code part? | ||
+ | |||
+ | <code c> | ||
+ | int x = 0; | ||
+ | |||
+ | switch(x) | ||
+ | { | ||
+ | |||
+ | case 1: cout << " | ||
+ | |||
+ | case 0: cout << " | ||
+ | |||
+ | case 2: cout << " | ||
+ | |||
+ | } | ||
+ | </ | ||
+ | 3. In which cases //switch// structure should be used? | ||
+ | === === | ||
+ | <box # | ||
+ | <box # | ||
+ | === Looping === | ||
+ | <box # | ||
+ | <box # | ||
+ | |||
+ | == for == | ||
+ | **//for//** is a cycle operator that allows specifying the number of times when the same statements will be executed. In this way, similar to the //loop// function it allows to control the program execution. Each time when all statements in the body of the cycle are executed is called the **iteration**. In this way, the cycle is one of the basic programming techniques that is used for all programs and automation in general. | ||
+ | |||
+ | The construction of a //for// cycle is the following: | ||
+ | <code c> | ||
+ | for (initialization ; condition ; operation with the cycle variable) { | ||
+ | //The body of the cycle | ||
+ | } | ||
+ | </ | ||
+ | |||
+ | Three parts of the //for// construction is the following: | ||
+ | * ** initialisation** section usually initialises the value of the variable that will be used to iterate the cycle; this value can be 0 or any other value; | ||
+ | * **condition** allows managing the number of cycle iterations; the statements in the body of the cycle are executed when the condition is //TRUE//; | ||
+ | * **operations with the cycle variable** allows defining the number of cycle iterations. | ||
+ | |||
+ | The example of the //for// cycle: | ||
+ | <code c> | ||
+ | for (int i = 0; i < 4; i = i + 1) | ||
+ | { | ||
+ | digitalWrite(13, | ||
+ | delay(1000); | ||
+ | digitalWrite(13, | ||
+ | delay(1000); | ||
+ | } | ||
+ | </ | ||
+ | On the initialization of the //for// cycle the variable //i// = 0 is defined. The condition states that the //for// cycle will be executed while the value of variable //i// will be less than 4 (//i// < 4). In the operation with the cycle variable it is increased by 1 each time when the cycle is repeated. | ||
+ | |||
+ | In this example above, the LED that is connected to the pin 13 of the Arduino board will turn on/off four times. | ||
+ | |||
+ | == while == | ||
+ | **// | ||
+ | |||
+ | The construction of the //while// cycle is the following: | ||
+ | <code c> | ||
+ | while (condition that is TRUE) | ||
+ | { | ||
+ | //The body of the cycle | ||
+ | } | ||
+ | </ | ||
+ | |||
+ | That way the //while// cycle can be used as a good instrument for the execution of a previously unpredictable program. For example, if it is necessary to wait until the signal from pin 2 reaches the defined voltage level – 100, the following code can be used: | ||
+ | |||
+ | <code c> | ||
+ | int inputVariable = analogRead(2); | ||
+ | while (inputVariable < 100) | ||
+ | { | ||
+ | digitalWrite(13, | ||
+ | delay(10); | ||
+ | digitalWrite(13, | ||
+ | delay(10); | ||
+ | inputVariable = analogRead(2); | ||
+ | } | ||
+ | </ | ||
+ | |||
+ | In the cycle, the LED that is connected to the pin 13 of the Arduino board will be turned on/off while the signal will reach the specified level. | ||
+ | |||
+ | |||
+ | == do...while == | ||
+ | The // | ||
+ | |||
+ | The construction of a //do while// cycle is the following: | ||
+ | <code c> | ||
+ | do { | ||
+ | //The body of the cycle | ||
+ | } while (condition that is TRUE); | ||
+ | </ | ||
+ | |||
+ | If the same code is taken from the //while// loop example and used in the // | ||
+ | <code c> | ||
+ | int inputVariable = analogRead(2); | ||
+ | do { | ||
+ | digitalWrite(13, | ||
+ | delay(10); | ||
+ | digitalWrite(13, | ||
+ | delay(10); | ||
+ | inputVariable = analogRead(2); | ||
+ | } while (inputVariable < 100); | ||
+ | </ | ||
+ | |||
+ | **Check Yourself** | ||
+ | |||
+ | 1. What is a kind of the loop, where the condition is checked after the loop body is executed? | ||
+ | |||
+ | 2. How long will the operators in the body of the loop operate [while (//x// < 100)]? | ||
+ | |||
+ | 3. What value will be for variable //a// after code executing? <code C> int a; for(a = 0; a < 10; a++) {} </ | ||
+ | |||
+ | 4. Which of the following operators are not loop(s) in Arduino IDE? | ||
+ | * // | ||
+ | * //while//, | ||
+ | * //repeat until//, | ||
+ | * //for//. | ||
+ | === === | ||
+ | <box # | ||
+ | <box # | ||
+ | === Interrupts and Sub-Programs === | ||
+ | <box # | ||
+ | <box # | ||
+ | |||
+ | == Functions == | ||
+ | Functions are the set of statements that are executed always when the function is called. Two functions that were mentioned before are already known – //setup()// and //loop()//. The programmer is usually trying to make several functions that contain all the statements and then to call them in the //setup()// or //loop()// functions. | ||
+ | |||
+ | The structure of the function is following: | ||
+ | <code c> | ||
+ | type functionName(arguments) //A return type, name and arguments of the function | ||
+ | { | ||
+ | //The body of a function – statements to execute | ||
+ | } | ||
+ | </ | ||
+ | |||
+ | For the example, a function that periodically turns on and off the LED is created: | ||
+ | |||
+ | <code c> | ||
+ | void exampleFunction() | ||
+ | { | ||
+ | digitalWrite(13, | ||
+ | delay(1000); | ||
+ | digitalWrite(13, | ||
+ | delay(1000); | ||
+ | } | ||
+ | </ | ||
+ | |||
+ | In the example code can be seen that the return type of a// | ||
+ | |||
+ | This function should be called inside the //loop()// function in the following way: | ||
+ | |||
+ | <code c> | ||
+ | void loop() | ||
+ | { | ||
+ | exampleFunction(); | ||
+ | } | ||
+ | </ | ||
+ | |||
+ | The whole code in the Arduino environment looks like this: | ||
+ | |||
+ | <code c> | ||
+ | void loop() | ||
+ | { | ||
+ | exampleFunction(); | ||
+ | } | ||
+ | |||
+ | void exampleFunction() | ||
+ | { | ||
+ | digitalWrite(13, | ||
+ | delay(1000); | ||
+ | digitalWrite(13, | ||
+ | delay(1000); | ||
+ | } | ||
+ | </ | ||
+ | |||
+ | It can be seen that the function is defined outside the //loop()// or //setup()// functions. | ||
+ | |||
+ | When some specific result must be returned as a result of a function, then the function return type should be indicated, for example: | ||
+ | |||
+ | <code c> | ||
+ | //the return type is " | ||
+ | int sumOfTwoNumbers(int x, int y) | ||
+ | { | ||
+ | //the value next to the " | ||
+ | //this is what will be returned as a result. | ||
+ | return (x+y); | ||
+ | } | ||
+ | </ | ||
+ | |||
+ | In the //loop()// this function would be called in a following way: | ||
+ | <code c> | ||
+ | void loop() | ||
+ | { | ||
+ | //the call of the defined function inside loop() | ||
+ | int result = sumOfTwoNumbers(2, | ||
+ | } | ||
+ | </ | ||
+ | |||
+ | == Interrupts == | ||
+ | |||
+ | // | ||
+ | |||
+ | IRS should be as short as possible, and the return type of it is void. Some of normal Arduino functions do not work or behave differently in the IRS, for example, //delay()// function does not work in the IRS. Variables, used in the IRS must be volatile variables. | ||
+ | |||
+ | Interrupts are used to detect important real-time events, which occur during the normal code execution of the code, without continuously checking them, like pushing a button. | ||
+ | |||
+ | Different Arduino types have different external interrupt pin availability. In most Arduino boards pins, number 2 and 3 are used for interrupts. | ||
+ | |||
+ | To attach interrupt, the function // | ||
+ | - //pin// – the number of a pin number where the interrupt signal generating device will be attached. | ||
+ | - //ISR// – the name of a function of interrupt service routine. | ||
+ | - //mode// – defines when interrupt signal is triggered. There are four basic //mode// values: | ||
+ | * //LOW// – interrupt is triggered when the pin value is //LOW//, | ||
+ | * //HIGH// – interrupt is triggered when the pin value is // | ||
+ | * //CHANGE// – interrupt is triggered when the pin value is changed, | ||
+ | * //RISING// – interrupt is triggered when the pin value is changed from //LOW// to //HIGH//. | ||
+ | |||
+ | The example program that uses interrupt: | ||
+ | |||
+ | <code c> | ||
+ | volatile bool button =0; //A variable to save button state | ||
+ | |||
+ | void setup() { | ||
+ | //Define LED pin | ||
+ | pinMode(13, | ||
+ | //Define button pin | ||
+ | pinMode(2, | ||
+ | //Attach interrupt to button pin | ||
+ | attachInterrupt(digitalPinToInterrupt(2), | ||
+ | } | ||
+ | |||
+ | void ButtonIRS() { //IRS function | ||
+ | button =!button; | ||
+ | } | ||
+ | |||
+ | void loop() { | ||
+ | digitalWrite (13, | ||
+ | } | ||
+ | </ | ||
+ | |||
+ | **Check Yourself** | ||
+ | |||
+ | 1. What are the built-in functions used for? | ||
+ | * To reduce the size of the program. | ||
+ | * To delete unnecessary functions. | ||
+ | * To simplify the source file. | ||
+ | * To increase the speed of the program. | ||
+ | |||
+ | 2. Which of the following statements are true? | ||
+ | * Built-in functions must return a value. | ||
+ | * Built-in functions cannot return values. | ||
+ | * The compiler can ignore the declaration of the built-in function. | ||
+ | * Built-in functions cannot contain more than 10 lines of code. | ||
+ | |||
+ | 3. Is it possible to guarantee that the declared built-in function is really built-in? | ||
+ | * Guarantee is not possible, in each case it is different. | ||
+ | |||
+ | * Can be confidently ensured that the function you have declared as built-in is really built-in. | ||
+ | | ||
+ | === === | ||
+ | <box # | ||
+ | <box # | ||
+ | === Timing === | ||
+ | <box # | ||
+ | <box # | ||
+ | |||
+ | == Delay == | ||
+ | The simplest solution to make functions work for a certain time is to use //delay()// ((https:// | ||
+ | //delay()// function stops program execution for instructed time. | ||
+ | |||
+ | Blinking LED is a simple demonstration of delay functionality: | ||
+ | <code c> | ||
+ | digitalWrite(LED_BUILTIN, | ||
+ | delay(1000); | ||
+ | digitalWrite(LED_BUILTIN, | ||
+ | delay(1000); | ||
+ | </ | ||
+ | |||
+ | Limitations that come with using // | ||
+ | |||
+ | == Millis == | ||
+ | // | ||
+ | |||
+ | Here is an example code of blinking LED using // | ||
+ | |||
+ | <code c> | ||
+ | //Unsigned long should be used to store time values | ||
+ | //Store value of current millis reading | ||
+ | unsigned long currentTime = 0; | ||
+ | //Store value of time when last time the LED state was switched | ||
+ | unsigned long previousTime = 0; | ||
+ | |||
+ | bool ledState = LOW; //Varible for setting LED state | ||
+ | |||
+ | const int stateChangeTime = 1000; //Time at which switch LED states | ||
+ | |||
+ | void setup() { | ||
+ | pinMode (LED_BUILTIN, | ||
+ | } | ||
+ | |||
+ | void loop() { | ||
+ | currentTime = millis(); //Read and store current time | ||
+ | |||
+ | //Calculate passed time since last stateChange | ||
+ | //If more time has passed than stateChangeTime, | ||
+ | if (currentTime - previousTime >= stateChangeTime) { | ||
+ | | ||
+ | previousTime = currentTime; | ||
+ | ledState = !ledState; //Change LED state to oposite | ||
+ | digitalWrite(LED_BUILTIN, | ||
+ | } | ||
+ | } | ||
+ | </ | ||
+ | |||
+ | == Protothread == | ||
+ | |||
+ | Protothread is a mechanism for concurrent programming in embedded systems with limited resources. In Arduino, it can be used to achieve a periodical function call, like sensor reading, output state change, calculations etc. Most Arduino used microcontrollers have only one core; it can’t execute multiple functions simultaneously. By using // | ||
+ | |||
+ | In the example, code second LED is added, to demonstrate how to blink two LED’s concurrent with different frequencies. In the same manner, servo control, button reading and other functionality can be added. | ||
+ | |||
+ | <code c> | ||
+ | //Unsigned long should be used to store time values | ||
+ | //Store value of current millis reading | ||
+ | unsigned long currentTime = 0; | ||
+ | //Store value of time when last time LED1 state was switched | ||
+ | unsigned long previousTime1 = 0; | ||
+ | //Store value of time when last time LED2 state was switched | ||
+ | unsigned long previousTime2 = 0; | ||
+ | |||
+ | bool led1State = LOW; //Varible for setting LED1 state | ||
+ | bool led2State = LOW; //Varible for setting LED2 state | ||
+ | |||
+ | const int stateChangeTimeLed1 = 1000; //Time at which switch LED1 states | ||
+ | const int stateChangeTimeLed2 = 200; //Time at which switch LED2 states | ||
+ | |||
+ | void setup() { | ||
+ | pinMode (LED_BUILTIN, | ||
+ | pinMode (2,OUTPUT); //LED2 setup | ||
+ | } | ||
+ | |||
+ | void loop() { | ||
+ | currentTime = millis(); //Read and store current time | ||
+ | |||
+ | //Calculate passed time since the last stateChange | ||
+ | //If more time has passed than stateChangeTime, | ||
+ | | ||
+ | if (currentTime - previousTime1 >= stateChangeTimeLed1) { | ||
+ | previousTime1 = currentTime; | ||
+ | led1State = !led1State; //Change LED1 state to oposite | ||
+ | digitalWrite(LED_BUILTIN, | ||
+ | } | ||
+ | if (currentTime - previousTime2 >= stateChangeTimeLed2) { | ||
+ | previousTime2 = currentTime; | ||
+ | led2State = !led2State; //Change led2state to oposite | ||
+ | digitalWrite(2, | ||
+ | } | ||
+ | } | ||
+ | </ | ||
+ | |||
+ | There are dedicated libraries made by the Arduino community to implement protothreads ((http:// | ||
+ | |||
+ | |||
+ | **Check Yourself** | ||
+ | |||
+ | 1. What are the drawbacks of using // | ||
+ | * Program execution stops. | ||
+ | * Can’t read sensors during // | ||
+ | * Simple code. | ||
+ | |||
+ | 2. What is the difference between //delay()// and // | ||
+ | |||
+ | 3. Can Arduino run truly parallel programs? | ||
+ | |||
+ | 4. How is concurrency achieved on Arduino? | ||
+ | | ||
+ | === === | ||
+ | <box # | ||
+ | <box # | ||
+ | === Reading GPIOs, Outputting Data and Tracing === | ||
+ | <box # | ||
+ | <box # | ||
+ | |||
+ | == Digital I/O == | ||
+ | The digital inputs and output of Arduino allow connecting different type of sensors and actuators to the board. Digital signals can take two values – //HIGH//(1) or //LOW//(0). These types of inputs and outputs are used in applications when the signal can have only two states. | ||
+ | |||
+ | **pinMode()** | ||
+ | |||
+ | The function // | ||
+ | |||
+ | The syntax of a function is the following: | ||
+ | <code c> | ||
+ | pinMode(pin, | ||
+ | </ | ||
+ | |||
+ | The parameter //pin// is the number of the pin. | ||
+ | |||
+ | The parameter //mode// can have three different values – //INPUT//, //OUTPUT//, // | ||
+ | |||
+ | **digitalWrite()** | ||
+ | |||
+ | The function // | ||
+ | |||
+ | The syntax of a function is the following: | ||
+ | <code c> | ||
+ | digitalWrite(pin, | ||
+ | </ | ||
+ | |||
+ | The parameter //pin// is the number of the pin. | ||
+ | The parameter //value// can take values //HIGH// or //LOW//. If the mode of the pin is set to the //OUTPUT//, the //HIGH// sets voltage to +5 V and //LOW// – to 0 V. | ||
+ | |||
+ | It is also possible to use this function for pins that are set to have the INPUT mode. In this case, //HIGH// or //LOW// values enable or disable the internal pull-up resistor. | ||
+ | |||
+ | **digitalRead()** | ||
+ | |||
+ | The function // | ||
+ | |||
+ | The syntax of a function is the following: | ||
+ | <code c> | ||
+ | digitalRead(pin) | ||
+ | </ | ||
+ | |||
+ | The parameter //pin// is the number of the pin. | ||
+ | |||
+ | On the opposite as the functions viewed before, this one has the return type, and it can take a value of //HIGH// or //LOW//. | ||
+ | |||
+ | |||
+ | == Analog I/O == | ||
+ | The analogue inputs and outputs are used when the signal can take a range of values, unlike the digital signal that takes only two values (//HIGH// or //LOW//). For measuring the analogue signal, Arduino has built-in **analogue-to-digital converter** (ADC) that returns the digital value of the voltage level. | ||
+ | |||
+ | **analogWrite()** | ||
+ | |||
+ | The function // | ||
+ | |||
+ | The syntax of a function is the following: | ||
+ | <code c> | ||
+ | analogWrite(pin, | ||
+ | </ | ||
+ | |||
+ | The parameter //pin// is the number of the pin. | ||
+ | |||
+ | The parameter //value// is the | ||
+ | |||
+ | This function does not have the return type. | ||
+ | |||
+ | **analogRead()** | ||
+ | |||
+ | The function // | ||
+ | |||
+ | The syntax of a function is the following: | ||
+ | <code c> | ||
+ | analogRead(pin) | ||
+ | </ | ||
+ | |||
+ | The parameter //pin// is the number of the pin whose value is read. | ||
+ | |||
+ | The return type of the function is the integer value between 0 and 1023. The reading of each analogue input takes around 100 ms that is 0.0001 s. | ||
+ | |||
+ | **Check Yourself** | ||
+ | |||
+ | 1. To assign the Arduino pin operation mode, which function is using? | ||
+ | * Function // | ||
+ | * Function // | ||
+ | * Directive //# | ||
+ | |||
+ | 2. What command for analogue input read is used? | ||
+ | |||
+ | 3. The digital output on Arduino works as a power source with voltage? | ||
+ | |||
+ | * 5 V. | ||
+ | * 12 V. | ||
+ | * 3.3 V. | ||
+ | ===== ===== | ||
+ | <box # | ||
+ | <box # | ||
+ | ===== Espressif SoC Overview ===== | ||
+ | <box # | ||
+ | <box # | ||
+ | |||
+ | Arduino, along with a vast amount of peripheral boards, lacks integration of the networking capabilities in one SoC. Espressif ESP series was the natural answer for this disadvantage as their ESP 8266 with integrated WiFi, introduced in 2014, is widely recognised as a turning point for the IoT market, delivering de-facto fully functional IoT chip, providing high performance and low power to the end users and developers. ESP 32 launched in 2016 brought even more disrupting effect to the IoT ecosystems, introducing additional Bluetooth interface to the above. By the January 2018 company announced they delivered to the market 100 000 000 ((https:// | ||
+ | |||
+ | Following chapters provide an overview of the networking programming with the use of ESP SoCs. | ||
+ | |||
+ | <note tip> | ||
+ | " 4.3. [[en: | ||
+ | </ | ||
+ | |||
+ | <note important> | ||
+ | The major difference is that ESP SoCs (both 8266 and 32) use 3.3 V logic, while most (but not all!) Arduinos use 5 V logic. This can be easily handled using one or bi-directional voltage converters/ | ||
+ | |||
+ | * " | ||
+ | |||
+ | * " | ||
+ | |||
+ | * " | ||
+ | ==== ==== | ||
+ | <box # | ||
+ | <box # | ||
+ | ====Espressif SoC ==== | ||
+ | <box # | ||
+ | <box # | ||
+ | |||
+ | Espressif System-on-chip (SoC) devices are low-cost microcontrollers with full TCP/IP stack capability produced by Shanghai-based Chinese manufacturer, | ||
+ | |||
+ | * ESP8266, | ||
+ | * ESP32. | ||
+ | |||
+ | ===ESP 8266 General Information=== | ||
+ | The ESP8266 is a low-cost system on chip (SoC) microcontroller with WiFi and full TCP/IP stack capability ((https:// | ||
+ | The ESP8285 is an ESP8266 with 1 MiB of built-in flash, allowing for single-chip devices capable of connecting to WiFi. The successor to these microcontroller chips is the ESP32. For now, the ESP8366 family includes the following chip: | ||
+ | * ESP8266EX (Figure {{ref> | ||
+ | |||
+ | <figure esp8266EX_chip> | ||
+ | {{ : | ||
+ | < | ||
+ | </ | ||
+ | |||
+ | == Esp8266 Architecture Overview == | ||
+ | |||
+ | Main standard features of the ESP8266EX are: | ||
+ | |||
+ | **Processor** | ||
+ | * **Main processor: | ||
+ | |||
+ | **Memory** | ||
+ | * 32 KiB instruction RAM. | ||
+ | * 32 KiB instruction cache RAM. | ||
+ | * 80 KiB user data RAM. | ||
+ | * 16 KiB ETS system data RAM. | ||
+ | * External QSPI flash: up to 16 MiB is supported (512 KiB to 4 MiB typically included). | ||
+ | |||
+ | **Interfaces** | ||
+ | * IEEE 802.11 b/g/n WiFi . | ||
+ | * Integrated TR switch, balun, LNA, power amplifier and matching network WEP or WPA/WPA2 authentication, | ||
+ | * 16 GPIO pins. | ||
+ | * SPI. | ||
+ | * I²C (software implementation). | ||
+ | * I²S interfaces with DMA (sharing pins with GPIO). | ||
+ | * UART on dedicated pins, plus a transmit-only UART can be enabled on GPIO2. | ||
+ | * 10-bit ADC (successive approximation ADC). | ||
+ | |||
+ | Figure {{ref> | ||
+ | |||
+ | <figure esp8266_main_f> | ||
+ | {{ : | ||
+ | < | ||
+ | </ | ||
+ | |||
+ | ==ESP8266 Modules== | ||
+ | |||
+ | There are many ESP8266 based modules on the market ((https:// | ||
+ | |||
+ | The most popular are these produced by AI-Thinker and remain the most widely available ((https:// | ||
+ | * ESP-01 (512 KiB Flash), | ||
+ | * ESP-01S (1 MiB Flash), | ||
+ | * ESP-12 (FCC and CE approved), | ||
+ | * ESP-12E, | ||
+ | * ESP-12F (4 MiB Flash, FCC and CE approved). | ||
+ | | ||
+ | * Sparkfun ESP8266 Thing, | ||
+ | * Wemos D1 mini, D1 mini Pro ((https:// | ||
+ | |||
+ | The Espressif company also produces ready-made modules using the aforementioned chip. This is the series of ESP8266-based modules made by Espressif (Table {{ref> | ||
+ | |||
+ | <table esp8266_modules> | ||
+ | < | ||
+ | ^<fs xx-small> | ||
+ | |<fs xx-small> | ||
+ | |<fs xx-small> | ||
+ | |<fs xx-small> | ||
+ | |<fs xx-small> | ||
+ | </ | ||
+ | |||
+ | The most widely used and chipest ESP-01 is presented on (Figure {{ref> | ||
+ | |||
+ | <figure esp01> | ||
+ | {{ : | ||
+ | < | ||
+ | </ | ||
+ | |||
+ | <figure esp01pin> | ||
+ | {{ : | ||
+ | < | ||
+ | </ | ||
+ | |||
+ | Module ESP12F with pinout is presented on (Figure {{ref> | ||
+ | |||
+ | <figure esp12f> | ||
+ | {{ : | ||
+ | < | ||
+ | </ | ||
+ | <figure esp12fpin> | ||
+ | {{ : | ||
+ | < | ||
+ | </ | ||
+ | |||
+ | Among the other modules, it is worth to be interested in WEMOS modules ((https:// | ||
+ | |||
+ | <figure WemosD1mini> | ||
+ | {{ : | ||
+ | {{ : | ||
+ | < | ||
+ | </ | ||
+ | |||
+ | <figure WemosD1pro> | ||
+ | {{ : | ||
+ | < | ||
+ | </ | ||
+ | |||
+ | <figure Wemosshields> | ||
+ | {{ : | ||
+ | < | ||
+ | </ | ||
+ | |||
+ | ESP32 NodeMCU | ||
+ | |||
+ | <figure esp32_nodepins> | ||
+ | {{ : | ||
+ | < | ||
+ | </ | ||
+ | |||
+ | |||
+ | ===ESP32 General Information=== | ||
+ | ESP32 is a low-cost, low-power system on a chip (SoC) series microcontrollers with WiFi & dual-mode Bluetooth capabilities ((https:// | ||
+ | * ESP32-D0WDQ6 (Figure {{ref> | ||
+ | * ESP32-D0WD (Figure {{ref> | ||
+ | * ESP32-D2WD (Figure {{ref> | ||
+ | * ESP32-S0WD (Figure {{ref> | ||
+ | * ESP32-PICO-D4 -- SiP (system in package) (Figure {{ref> | ||
+ | |||
+ | |||
+ | <figure esp32_d0wdq6> | ||
+ | {{ : | ||
+ | < | ||
+ | </ | ||
+ | |||
+ | <figure esp32_d0wd> | ||
+ | {{ : | ||
+ | < | ||
+ | </ | ||
+ | |||
+ | <figure esp32_d2wd> | ||
+ | {{ : | ||
+ | < | ||
+ | </ | ||
+ | |||
+ | <figure esp32_s0wd> | ||
+ | {{ : | ||
+ | < | ||
+ | </ | ||
+ | |||
+ | <figure esp32_pico_d4> | ||
+ | {{ : | ||
+ | < | ||
+ | </ | ||
+ | |||
+ | |||
+ | |||
+ | == ESP32 Architecture Overview == | ||
+ | (Figure {{ref> | ||
+ | |||
+ | **Processors** | ||
+ | * **Main processor: | ||
+ | * **Cores**: 2 or 1 (depending on variation). (All chips in the ESP32 series are dual-core except for ESP32-S0WD, which is single-core.) | ||
+ | * Internal 8 Mhz oscillator with calibration. | ||
+ | * External 2 MHz to 60 MHz crystal oscillator (40 MHz only for WiFi/BT functionality). | ||
+ | * External 32 kHz crystal oscillator for RTC with calibration. | ||
+ | * **Clock frequency: | ||
+ | * **Performance: | ||
+ | * **Ultra low power co-processor: | ||
+ | **Wireless connectivity** | ||
+ | * **WiFi:** 802.11 b/g/n/e/i (802.11n @ 2.4 GHz up to 150 Mbit/s) with simultaneous Infrastructure BSS Station mode/ | ||
+ | * **Bluetooth: | ||
+ | **Memory: Internal memory** | ||
+ | * **ROM:** 448 KiB (for booting and core functions). | ||
+ | * **SRAM:** 520 KiB (for data and instruction). | ||
+ | * **RTC fast SRAM:** 8 KiB (for data storage and main CPU during RTC Boot from the deep-sleep mode). | ||
+ | * **RTC slow SRAM:** 8 KiB (for co-processor accessing during deep-sleep mode). | ||
+ | * **eFuse:** 1 Kibit (of which 256 bits are used for the system (MAC address and chip configuration) and the remaining 768 bits are reserved for customer applications, | ||
+ | * **Embedded flash** (flash connected internally via IO16, IO17, SD_CMD, SD_CLK, SD_DATA_0 and SD_DATA_1 on ESP32-D2WD and ESP32-PICO-D4): | ||
+ | | ||
+ | | ||
+ | | ||
+ | **External Flash & SRAM** | ||
+ | * ESP32 supports up to four 16 MiB external QSPI flashes and SRAMs with hardware encryption based on AES to protect developers' | ||
+ | * Up to 16 MiB of external flash are memory-mapped onto the CPU code space, supporting 8-bit, 16-bit and 32-bit access. Code execution is supported. | ||
+ | * Up to 8 MiB of external flash/SRAM memory is mapped onto the CPU data space, supporting 8-bit, 16-bit and 32-bit access. Data-read is supported on the flash and SRAM. Data-write is supported on the SRAM. | ||
+ | ESP32 chips with embedded flash do not support the address mapping between external flash and peripherals. | ||
+ | |||
+ | **Peripheral Input/ | ||
+ | * Rich peripheral interface with DMA that includes capacitive touch (10× touch sensors). | ||
+ | * 12-bit ADCs (analog-to-digital converter) up to 18 channels. | ||
+ | * 2 × 8 bit DACs (digital-to-analog converter). | ||
+ | * 2 × I²C (Inter-Integrated Circuit. | ||
+ | * 3x UART (universal asynchronous receiver/ | ||
+ | * CAN 2.0 (Controller Area Network). | ||
+ | * 4 × SPI (Serial Peripheral Interface). | ||
+ | * 2 × I²S (Integrated Inter-IC Sound). | ||
+ | * RMII (Reduced Media-Independent Interface). | ||
+ | * Motor PWM (pulse width modulation). | ||
+ | * LED PWM up to 16 channels. | ||
+ | * Hall sensor. | ||
+ | * Internal temperature sensor. | ||
+ | **Security** | ||
+ | * Secure boot. | ||
+ | * Flash encryption. | ||
+ | * IEEE 802.11 standard security features all supported, including WFA, WPA/WPA2 and WAPI. | ||
+ | * 1024-bit OTP, up to 768-bit for customers. | ||
+ | * Cryptographic hardware acceleration: | ||
+ | * | ||
+ | * SHA-2, | ||
+ | * | ||
+ | * elliptic curve cryptography (ECC), | ||
+ | * random number generator (RNG). | ||
+ | |||
+ | < | ||
+ | {{ : | ||
+ | < | ||
+ | </ | ||
+ | |||
+ | ==ESP32 Modules== | ||
+ | |||
+ | The company also produces ready-made modules using the aforementioned processors. These modules combines ESP32 microcontroller and additional components mounted on PCB with EM shield: | ||
+ | * ESP32-WROOM-32 with 4 MiB flash memory, and antenna on PCB (Figure {{ref> | ||
+ | * ESP32-WROOM-U with 4 MiB flash memory and u.fl antenna conector (Figure {{ref> | ||
+ | * ESP32-WROVER -- with 4 MiB flash memory, 4 MiB pseudo static RAM and antenna on PCB (Figure {{ref> | ||
+ | * ESP32-WROVER-I -- as ESP32-WROVER with additional u.fl antenna connector (Figure {{ref> | ||
+ | |||
+ | <figure esp32_wroom> | ||
+ | {{ : | ||
+ | < | ||
+ | </ | ||
+ | | ||
+ | <figure esp32_wroomu> | ||
+ | {{ : | ||
+ | < | ||
+ | </ | ||
+ | |||
+ | <figure esp32_wroover> | ||
+ | {{ : | ||
+ | < | ||
+ | </ | ||
+ | |||
+ | <figure esp32_wrooveri> | ||
+ | {{ : | ||
+ | < | ||
+ | </ | ||
+ | |||
+ | |||
+ | ==ESP32 Development Kits== | ||
+ | To accelerate the design of circuits, developers can use specially prepared sets with ESP32 which are ready to use. The original Espressif best known small development boards are: | ||
+ | * ESP32-DevkitC (Figure {{ref> | ||
+ | * ESP32-PICO-KIT-V4 (Figure {{ref> | ||
+ | |||
+ | <figure esp32_devkitc> | ||
+ | {{ : | ||
+ | < | ||
+ | </ | ||
+ | |||
+ | <figure esp32_picokit> | ||
+ | {{ : | ||
+ | < | ||
+ | </ | ||
+ | |||
+ | ==General Purpose Input-Output (GPIO) Connector== | ||
+ | |||
+ | Each ESP32 is equipped with standard 38/40-pis male connector containing universal GPIO ports, VCC 3.3/5 V, GND, CLK, I2C/SPI buses pins which developers can use to connect their external sensors, switches and other controlled devices to the ESP32 board and then program their behaviour within the code loaded to the board. | ||
+ | |||
+ | * ESP32-DevkitC v2 pins (Figure {{ref> | ||
+ | |||
+ | |||
+ | <figure esp32_devkitpins> | ||
+ | {{ : | ||
+ | < | ||
+ | </ | ||
+ | |||
+ | * ESP32-PICO D4 pins (Figure {{ref> | ||
+ | |||
+ | <figure esp32_picokitpins> | ||
+ | {{ : | ||
+ | < | ||
+ | </ | ||
+ | |||
+ | * ESP32 Wemos Pro pins (Figure {{ref> | ||
+ | |||
+ | <figure esp32_wemospins> | ||
+ | {{ : | ||
+ | < | ||
+ | </ | ||
+ | ==== ==== | ||
+ | <box # | ||
+ | <box # | ||
+ | ==== Espressif SoC Networking ==== | ||
+ | <box # | ||
+ | <box # | ||
+ | |||
+ | Using Espressif SoC devices in Arduino platform we can use all the previously described Arduino examples for sensors and actuators. But the most interesting are are those that use wireless networking functions. Both Espressif chip ESP32 and ESP8266 | ||
+ | * as WiFi client connected to WiFi router (Figure {{ref> | ||
+ | <figure esp_client> | ||
+ | {{ : | ||
+ | < | ||
+ | </ | ||
+ | * as independent WiFi access point (Figure {{ref> | ||
+ | <figure esp_ap> | ||
+ | {{ : | ||
+ | < | ||
+ | </ | ||
+ | * as a repeater with devices connected to ESP and ESP connected to external router (Figure {{ref> | ||
+ | <figure esp_both> | ||
+ | {{ : | ||
+ | < | ||
+ | </ | ||
+ | * as client and server in mesh network (Figure {{ref> | ||
+ | <figure esp_mesh> | ||
+ | {{ : | ||
+ | < | ||
+ | </ | ||
+ | ESP32 can also use Bluetooth networking in the same configuration as WiFi. | ||
+ | |||
+ | ==== ==== | ||
+ | <box # | ||
+ | <box # | ||
+ | ==== ESP Programming Fundamentals ==== | ||
+ | <box # | ||
+ | <box # | ||
+ | |||
+ | The following sub-chapters cover programming fundamentals for ESP chips in C/C++, which complies with the most C/C++ notations and have some specific notations. Please note, this is a particular implementation of the programming, | ||
+ | |||
+ | |||
+ | <note tip>This manual refers to the particular version of the software (here Arduino IDE, ESP 8266 and ESP32 and related toolkits) available at the moment of writing of this book, thus accessing particular features may change over time along with the evolution of the platform. Please refer attached documentation (if any) and browse Internet resources to find lates guidances on how to configure development platform, when in doubt. | ||
+ | In particular, following links present up-to-date help on "how to start" guides with ESP 8266 and ESP32 platforms and Arduino IDE. Please refer here, when guides present in following sub-chapters are outdated: | ||
+ | * ESP 8266 Github ((https:// | ||
+ | * ESP 32 Github ((https:// | ||
+ | </ | ||
+ | |||
+ | |||
+ | Further reading: | ||
+ | |||
+ | * " | ||
+ | |||
+ | * " | ||
+ | |||
+ | * " | ||
+ | |||
+ | * " | ||
+ | |||
+ | * " | ||
+ | === === | ||
+ | <box # | ||
+ | <box # | ||
+ | === Setting Up Development Environment for ESP SoC Programming === | ||
+ | <box # | ||
+ | <box # | ||
+ | |||
+ | Following subchapters present guides for setting up the environment to enable you to use Arduino(C) IDE to develop solutions for ESP8266 and ESP32. Installation methodology varies much as ESP8266 is already integrated with so-called Board Manager in Ardiono(C) iDE, while ESP32 is somehow external to the Boards Manager and requires some steps to be done, to obtain fully integrated environment. Some of the steps vary in details among various operating systems you use (Windows/ | ||
+ | |||
+ | <note tip> | ||
+ | |||
+ | == Download and Run Arduino IDE == | ||
+ | We consider here software that is natively installed as a binary package on your operating system, not a WEB version of the IDE. To obtain the latest version of the binary package, visit the website ((https:// | ||
+ | <figure 8266-1> | ||
+ | {{: | ||
+ | < | ||
+ | </ | ||
+ | <note important> | ||
+ | <note important> | ||
+ | |||
+ | == Configuring Arduino IDE for ESP8266 Development == | ||
+ | Assuming you've purchased any of the ESP8266 development boards, it is essential to write the first program. In any case, you'll need a way to write, compile and upload your code to the ESP8266 SoC. Here Arduino(C) IDE comes handy, however before you start, you need to let the Arduino(C) IDE knows, how to compile and communicate with your ESP8266 chip. Below there is a short manual, presenting how to install development extension to the Arduino(C) IDE through the Boards Manager. Note, other solutions (i.e. manual installation via Github pull) is also possible, but we do not consider this option here. ESP8266 core for Arduino(C) IDE is maintained by the community, and the latest version is available here (along with up-to-date installation guide) ((https:// | ||
+ | |||
+ | |||
+ | **Install ESP8266 Boards via Board Manager** | ||
+ | |||
+ | Start Arduino(C) IDE (Figure {{ref> | ||
+ | <figure 8266-2> | ||
+ | {{: | ||
+ | < | ||
+ | </ | ||
+ | |||
+ | Enter application menu // | ||
+ | <figure 8266-4> | ||
+ | {{: | ||
+ | < | ||
+ | </ | ||
+ | |||
+ | and then go to the Additional Boards Manager URLs:, enter following URL and accept changes (press OK) (Figure {{ref> | ||
+ | < | ||
+ | http:// | ||
+ | </ | ||
+ | <figure 8266-5> | ||
+ | {{: | ||
+ | < | ||
+ | </ | ||
+ | |||
+ | Once finished, you need to tell the Board Manager, which definitions and tools to download. Open // | ||
+ | <figure 8266-6> | ||
+ | {{: | ||
+ | < | ||
+ | </ | ||
+ | and filter all boards entering " | ||
+ | <figure 8266-61> | ||
+ | {{: | ||
+ | < | ||
+ | </ | ||
+ | Note -- installation downloads number of resources over Internet connection and may take some time. | ||
+ | |||
+ | **Configure Project to Compile for ESP8266** | ||
+ | |||
+ | Once you're done with Arduino(C) IDE configuration now it is time to start programming. | ||
+ | The process above installs a number of board definitions. First, depending on the development kit you own, select the appropriate type of the development board in the Board Manager menu, i.e. WeMos D1 R2 & mini (Figure {{ref> | ||
+ | <figure 8266-7> | ||
+ | {{: | ||
+ | < | ||
+ | </ | ||
+ | |||
+ | |||
+ | **Communication Between Development Machine and ESP SoC** | ||
+ | |||
+ | Most of the ESP development boards come with integrated programming interface via serial to USB converter (usually CH340, CP210x, FDTI, Prolific, etc.) that you connect to the development machine using the USB cable. Connector standards vary, but nowadays the most popular seems to be Micro USB connector. There is also possible to upload your compilation using wireless transmission (OTA -- Over The Air), or dedicated programming device, but we do not consider it here as too complicated to implement (requires special firmware) and also insecure. You need to select correct device interface -- it differs, depending on the operating system you use, see details below how to identify it in your computer. | ||
+ | \\ | ||
+ | \\ | ||
+ | \\ | ||
+ | \\ | ||
+ | \\ | ||
+ | **Windows** | ||
+ | |||
+ | Look into the Device Manager to identify COM port, your board is represented by, in the Windows OS (Figure {{ref> | ||
+ | <figure winCOM> | ||
+ | {{: | ||
+ | < | ||
+ | </ | ||
+ | |||
+ | **Linux** | ||
+ | |||
+ | In case of the Linux distributions, | ||
+ | <figure uxCOM> | ||
+ | {{: | ||
+ | < | ||
+ | </ | ||
+ | |||
+ | **Mac OS** | ||
+ | |||
+ | The similar way to Linux distros, look for the devices using: <code bash>ls / | ||
+ | <figure uxMACCOM> | ||
+ | {{: | ||
+ | < | ||
+ | </ | ||
+ | |||
+ | |||
+ | **Configure Details for the SoC** | ||
+ | |||
+ | Now select appropriate device in the Arduino IDE (Figure {{ref> | ||
+ | <figure 8266-8> | ||
+ | {{: | ||
+ | < | ||
+ | </ | ||
+ | <figure 8266-9> | ||
+ | {{: | ||
+ | < | ||
+ | </ | ||
+ | |||
+ | **Troubleshooting Access Denied Error** | ||
+ | |||
+ | In case of the Linux and Mac, depending on the security context you run your Arduino(C) IDE, you may experience " | ||
+ | <code bash> | ||
+ | sudo usermod -a -G dialout $USER | ||
+ | </ | ||
+ | <code bash> | ||
+ | sudo chmod a+rw / | ||
+ | </ | ||
+ | |||
+ | <figure 8266-10> | ||
+ | {{: | ||
+ | < | ||
+ | </ | ||
+ | |||
+ | <figure 8266-11> | ||
+ | {{: | ||
+ | < | ||
+ | </ | ||
+ | A need to run one or two of the commands above strongly depends on the operating system configuration. | ||
+ | |||
+ | In case of the Windows OS, marking application to "Run as Administrator" | ||
+ | <figure 8266-12> | ||
+ | {{ : | ||
+ | < | ||
+ | </ | ||
+ | |||
+ | == Preparing ESP32 Development Environment With Arduino IDE == | ||
+ | ESP32 SoC is a continuation and extension to the ESP8266 SOCs. At the moment of writing this manual, installation of the ESP32 development environment is not supported via integrated Board Manager of the Arduino(C) IDE, as presented above in the ESP8266 section. Uploading your binary to the ESP32 chip via USB to serial converter requires Python as the ESP32 flashing tool is written in the form of the Python script. In case you're aware of what Python programming language is and how to install it on your machine, please refer to the Python website ((https:// | ||
+ | |||
+ | **Installing ESP32 Core for Arduino IDE** | ||
+ | |||
+ | Depending on the operating system you use, there is necessary to perform some steps to obtain a fully functional ESP32 development environment for Arduino(C) IDE. ESP32 core for Arduino is maintained by the community, and the latest version is available here (along with up-to-date installation guide) ((https:// | ||
+ | |||
+ | **Linux**\\ | ||
+ | A guide for the most popular distros (Ubuntu/ | ||
+ | |||
+ | //Modify user credentials// | ||
+ | This step is optional, see related ESP8266 section. Run following command in the terminal to add a user to the '' | ||
+ | <code bash> | ||
+ | sudo usermod -a -G dialout $USER | ||
+ | </ | ||
+ | //Download and install git client//\\ | ||
+ | Run following command in the terminal: | ||
+ | <code bash> | ||
+ | sudo apt-get install git | ||
+ | </ | ||
+ | //Download and install python tools and packages// | ||
+ | Run following commands in the terminal: | ||
+ | <code bash> | ||
+ | wget https:// | ||
+ | sudo python get-pip.py && \ | ||
+ | sudo pip install pyserial | ||
+ | </ | ||
+ | //Create destination folders and clone repository// | ||
+ | Assuming your Arduino IDE is installed in your home directory, ('' | ||
+ | <code bash> | ||
+ | mkdir -p ~/ | ||
+ | cd ~/ | ||
+ | git clone https:// | ||
+ | cd esp32 | ||
+ | </ | ||
+ | //Pull depending modules and tools//\\ | ||
+ | Run following commands in the terminal: | ||
+ | <code bash> | ||
+ | git submodule update --init --recursive && \ | ||
+ | cd tools && \ | ||
+ | python2 get.py | ||
+ | </ | ||
+ | Then start Arduino IDE. | ||
+ | |||
+ | **Windows**\\ | ||
+ | Installing ESP32 core for Arduino requires Git client, both GUI and bash as well as command line operations. | ||
+ | |||
+ | //Install Git and clone repository// | ||
+ | You can download and install Git ((https:// | ||
+ | Once installed, choose "Clone Existing Repository" | ||
+ | <figure ESP32-1> | ||
+ | {{ : | ||
+ | < | ||
+ | </ | ||
+ | Use ESP32 core for Arduino repository address as source: | ||
+ | < | ||
+ | https:// | ||
+ | </ | ||
+ | The destination folder depends on where you've installed Arduino IDE and your Windows user name. The common location is: | ||
+ | < | ||
+ | C:/ | ||
+ | </ | ||
+ | note, you do not need to create this folder manually. If you install fresh copy of the Arduino IDE, perhaps there will be no '' | ||
+ | Once entered //Source// and // | ||
+ | <figure ESP32-2> | ||
+ | {{ : | ||
+ | < | ||
+ | </ | ||
+ | |||
+ | //Pull depending modules//\\ | ||
+ | Use Git Bash command line (not a Windows command line!) to install dependencies (Figure {{ref> | ||
+ | Change directory to the esp32 git local copy then run submodules install: | ||
+ | <code bash> | ||
+ | cd Documents/ | ||
+ | </ | ||
+ | <code bash> | ||
+ | git submodule update --init --recursive | ||
+ | </ | ||
+ | <figure ESP32-4> | ||
+ | {{ : | ||
+ | < | ||
+ | </ | ||
+ | |||
+ | //Download ESP32 tools//\\ | ||
+ | Open Windows command line (not a Git Bash command line!), navigate to the tools folder (Figure {{ref> | ||
+ | < | ||
+ | cd C:/ | ||
+ | </ | ||
+ | then run: | ||
+ | < | ||
+ | get.exe | ||
+ | </ | ||
+ | <figure ESP332-6> | ||
+ | {{ : | ||
+ | < | ||
+ | </ | ||
+ | |||
+ | **Mac OS**\\ | ||
+ | Instruction for the Mac is similar to this for Linux. They require terminal to issue a set of commands to install ESP32 development kit and tools. | ||
+ | |||
+ | //Create destination folders and clone source//\\ | ||
+ | <code bash> | ||
+ | mkdir -p ~/ | ||
+ | cd ~/ | ||
+ | git clone https:// | ||
+ | cd esp32 | ||
+ | </ | ||
+ | //Pull depending modules and tools//\\ | ||
+ | Run following commands in the terminal: | ||
+ | <code bash> | ||
+ | git submodule update --init --recursive && \ | ||
+ | cd tools && \ | ||
+ | python get.py | ||
+ | </ | ||
+ | Then start Arduino IDE. | ||
+ | // | ||
+ | If you get the following error during installation: | ||
+ | < | ||
+ | xcrun: error: invalid active developer path (/ | ||
+ | missing xcrun at: / | ||
+ | </ | ||
+ | then install command line developer tools using: | ||
+ | <code bash> | ||
+ | xcode-select --install | ||
+ | </ | ||
+ | |||
+ | **Configure Project to Compile for ESP32** | ||
+ | |||
+ | Once ESP32 platform is installed, start Arduino IDE and you should see new board definitions, | ||
+ | <figure ESP32-10> | ||
+ | {{ : | ||
+ | < | ||
+ | </ | ||
+ | Refer to your board vendor for information about compatible configurations and setting up upload parameters. Detailed description and information on selecting communication port and upload speed is presented in the ESP8266 section, above. | ||
+ | === === | ||
+ | <box # | ||
+ | <box # | ||
+ | === ESP AT Networking === | ||
+ | <box # | ||
+ | <box # | ||
+ | |||
+ | == Flashing AT Firmware == | ||
+ | To use the ESP8266 chip as a modem (Figure {{ref> | ||
+ | <figure esp_at> | ||
+ | {{ : | ||
+ | < | ||
+ | </ | ||
+ | |||
+ | == Download Software== | ||
+ | |||
+ | - Download the latest ESP Flash Download Tool (v3.6.4 at the time of writing) from ((https:// | ||
+ | - Download the latest AT release from ((https:// | ||
+ | |||
+ | ==Flashing Procedure== | ||
+ | * Detect ESP8266 module parameters. Start ESP Flash Download Tool (" | ||
+ | |||
+ | <figure AT_flash> | ||
+ | {{ : | ||
+ | < | ||
+ | </ | ||
+ | * Gather information. Make a note of the flash memory size. In this example, we have a 32 Mbit flash. | ||
+ | * Load the correct size of combined AT binary firmware file (" | ||
+ | |||
+ | <figure AT_load> | ||
+ | {{ : | ||
+ | < | ||
+ | </ | ||
+ | * Then, click the START button and wait until the flashing process is over. | ||
+ | |||
+ | ==Reflashing Procedure== | ||
+ | If necessary, to restore the original firmware: | ||
+ | * Detect ESP8266 module parameters. Start ESP Flash Download Tool (" | ||
+ | |||
+ | <figure AT_flash1> | ||
+ | {{ : | ||
+ | < | ||
+ | </ | ||
+ | * From the downloaded AT firmware folder, open the " | ||
+ | < | ||
+ | # BOOT MODE | ||
+ | ## download | ||
+ | ### Flash size 8Mbit: 512KB+512KB | ||
+ | boot_v1.2+.bin | ||
+ | user1.1024.new.2.bin | ||
+ | esp_init_data_default.bin | ||
+ | blank.bin | ||
+ | |||
+ | ### Flash size 16Mbit: 512KB+512KB | ||
+ | boot_v1.5.bin | ||
+ | user1.1024.new.2.bin | ||
+ | esp_init_data_default.bin | ||
+ | blank.bin | ||
+ | |||
+ | ### Flash size 16Mbit-C1: 1024KB+1024KB | ||
+ | boot_v1.2+.bin | ||
+ | user1.2048.new.5.bin | ||
+ | esp_init_data_default.bin | ||
+ | blank.bin | ||
+ | |||
+ | ### Flash size 32Mbit: 512KB+512KB | ||
+ | boot_v1.2+.bin | ||
+ | user1.1024.new.2.bin | ||
+ | esp_init_data_default.bin | ||
+ | blank.bin | ||
+ | |||
+ | ### Flash size 32Mbit-C1: 1024KB+1024KB | ||
+ | boot_v1.2+.bin | ||
+ | user1.2048.new.5.bin | ||
+ | esp_init_data_default.bin | ||
+ | blank.bin | ||
+ | </ | ||
+ | * Indicate -- correct for your ESP8266 flash size -- firmware files & addresses. The firmware is broken down into several files. They need to be provided to the ESP Flash Download Tool, together with the corresponding addresses found in the readme.txt file above. For our ESP8266 example it should look like this (Figure {{ref> | ||
+ | <figure AT_reflash> | ||
+ | {{ : | ||
+ | < | ||
+ | </ | ||
+ | * Then, click the START button and wait until the flashing process is over. | ||
+ | |||
+ | |||
+ | === Basic ESP8266 Networking === | ||
+ | After uploading AT firmware and connecting module to PC, we can use ESP8266 as a modem with simple AT commands. | ||
+ | |||
+ | We can connect ESP8266 to PC with TTL-Serial-to-USB adapter, or we can use any microcontroller with a serial interface. The default baud rate settings are 115200, | ||
+ | < | ||
+ | and press enter. If you get OK, the ESP8266 module is ready to use. Let’s try out some other commands. For example, let’s figure out exactly what firmware version we’re dealing with. To do that, we’ll use the following command: | ||
+ | < | ||
+ | As a Wifi device ESP8266 can connect to the network in such modes: | ||
+ | * mode 1 -- client mode -- the ESP8266 connecting to an existing wireless network, | ||
+ | * mode 2 -- access point mode (AP) -- other wireless network devices can be connected to the ESP8266, | ||
+ | * mode 3 -- dual mode (router) -- the ESP8266 act as an access point and connect at the same time to an existing wireless network. | ||
+ | By default, the ESP8266’s stock firmware is set to AP mode. If you’d like to confirm that, send the following command: | ||
+ | < | ||
+ | You should get this response: +CWMODE:2, where 2 corresponds to AP mode. To switch ESP8266 to client device mode, we use the following command: | ||
+ | < | ||
+ | Now we can scan the airwaves for all WiFi access points in range. To do that, we send: | ||
+ | < | ||
+ | Then the ESP8266 will return a list of all the access points in range. In with each line will be item consisting of the security level of the access point, the network name, the signal strength, MAC address, and wireless channel used. Possible security levels of the access point < | ||
+ | * 0 -- open, | ||
+ | * 1 -- WEP, | ||
+ | * 2 -- WPA_PSK, | ||
+ | * 3 -- WPA2_PSK, | ||
+ | * 4 -- WPA_WPA2_PSK. | ||
+ | Now we can connect to the available access point using proper " | ||
+ | < | ||
+ | If everything is OK, the ESP8266 will answer: | ||
+ | < | ||
+ | WIFI CONNECTED | ||
+ | WIFI GOT IP | ||
+ | OK | ||
+ | </ | ||
+ | It means that ESP8266 is connected to the chosen AP and got a proper IP address. To check what the assigned address is we send the command: | ||
+ | < | ||
+ | |||
+ | To set up ESp8266 to behave both as a WiFi client as well as a WiFi Access point. | ||
+ | < | ||
+ | |||
+ | === === | ||
+ | <box # | ||
+ | <box # | ||
+ | === ESP Network Layers === | ||
+ | <box # | ||
+ | <box # | ||
+ | |||
+ | Programming networking services with ESP requires a connection on the networking layer between parties, mostly TCP.\\ | ||
+ | ESP SoC can act as Access Point (AP): a device you connect to, like you connect a notebook to the Internet router, and as a client: ESP then behaves like any wifi enabled device, i.e. tablet or mobile phone, connecting to the Internet infrastructure. Interestingly, | ||
+ | Below there is sample code, how to implement both modes, using ESP libraries that came during installation of the development environment for Arduino IDE.\\ | ||
+ | The third example shows how to send and receive a UDP packet while in client mode. It is the full solution to connect ESP to the NTP (Network Time Protocol) server to obtain current date and time from the Internet.\\ | ||
+ | Last examples show, how to make a handy WiFi scanner showing available networks nearby. | ||
+ | |||
+ | == ESP8266 AP (Access Point) Mode == | ||
+ | This sketch based on standard example demonstrates how to program ESP8266 in AP mode: | ||
+ | <code c> | ||
+ | |||
+ | #include < | ||
+ | #include < | ||
+ | #include < | ||
+ | |||
+ | /* Set these variables to your desired credentials. */ | ||
+ | const char *ssid = " | ||
+ | const char *password = " | ||
+ | |||
+ | ESP8266WebServer server(80); | ||
+ | |||
+ | void hRoot() { | ||
+ | server.send(200, | ||
+ | } | ||
+ | |||
+ | /* Initialization */ | ||
+ | void setup() { | ||
+ | delay(1500); | ||
+ | /* You can remove the password parameter if you want the AP to be open. */ | ||
+ | WiFi.softAP(ssid, | ||
+ | |||
+ | IPAddress myIP = WiFi.softAPIP(); | ||
+ | |||
+ | server.on("/", | ||
+ | server.begin(); | ||
+ | } | ||
+ | |||
+ | void loop() { | ||
+ | server.handleClient(); | ||
+ | } | ||
+ | </ | ||
+ | == ESP8266 Client Mode == | ||
+ | This sketch (standard example) demonstrates how to program ESP8266 in client mode: | ||
+ | <code c> | ||
+ | |||
+ | #include < | ||
+ | #include < | ||
+ | |||
+ | ESP8266WiFiMulti WiFiMulti; | ||
+ | |||
+ | void setup() { | ||
+ | delay(1000); | ||
+ | |||
+ | // We start by connecting to a WiFi network | ||
+ | WiFi.mode(WIFI_STA); | ||
+ | WiFiMulti.addAP(" | ||
+ | |||
+ | while(WiFiMulti.run() != WL_CONNECTED) { | ||
+ | delay(500); | ||
+ | } | ||
+ | delay(500); | ||
+ | } | ||
+ | |||
+ | |||
+ | void loop() { | ||
+ | const uint16_t port = 80; | ||
+ | const char * host = " | ||
+ | |||
+ | // Use WiFiClient class to create TCP connections | ||
+ | WiFiClient client; | ||
+ | |||
+ | if (!client.connect(host, | ||
+ | delay(5000); | ||
+ | return; | ||
+ | } | ||
+ | |||
+ | // This will send the request to the server | ||
+ | client.println(" | ||
+ | |||
+ | //read back one line from server | ||
+ | String line = client.readStringUntil(' | ||
+ | Serial.println(line); | ||
+ | |||
+ | Serial.println(" | ||
+ | client.stop(); | ||
+ | | ||
+ | Serial.println(" | ||
+ | delay(5000); | ||
+ | } | ||
+ | </ | ||
+ | |||
+ | == ESP8266 and UDP == | ||
+ | This sketch (based on standard example) demonstrates how to program ESP8266 as NTP client using UDP packets (send and receive): | ||
+ | <code c> | ||
+ | |||
+ | #include < | ||
+ | #include < | ||
+ | |||
+ | |||
+ | char ssid[] = " | ||
+ | char pass[] = " | ||
+ | |||
+ | unsigned int localPort = 2390; // local port to listen for UDP packets | ||
+ | |||
+ | // NTP servers | ||
+ | IPAddress ntpServerIP; | ||
+ | const char* ntpServerName[] = | ||
+ | | ||
+ | |||
+ | const int timeZone = 1; //Central European Time | ||
+ | int servernbr=0; | ||
+ | |||
+ | // NTP time stamp is in the first 48 bytes of the message | ||
+ | const int NTP_PACKET_SIZE = 48; | ||
+ | |||
+ | //buffer to hold incoming and outgoing packets | ||
+ | byte packetBuffer[ NTP_PACKET_SIZE]; | ||
+ | |||
+ | // A UDP instance to let us send and receive packets over UDP | ||
+ | WiFiUDP udp; | ||
+ | |||
+ | void setup() | ||
+ | { | ||
+ | Serial.begin(115200); | ||
+ | Serial.println(); | ||
+ | |||
+ | Serial.print(" | ||
+ | Serial.println(ssid); | ||
+ | | ||
+ | // WiFi.persistent(false); | ||
+ | WiFi.mode(WIFI_OFF); | ||
+ | delay(2000); | ||
+ | | ||
+ | // We start by connecting to a WiFi network | ||
+ | WiFi.mode(WIFI_STA); | ||
+ | delay(3000); | ||
+ | WiFi.begin(ssid, | ||
+ | | ||
+ | while (WiFi.status() != WL_CONNECTED) { | ||
+ | delay(500); | ||
+ | Serial.print(" | ||
+ | } | ||
+ | | ||
+ | Serial.println("" | ||
+ | | ||
+ | Serial.println(" | ||
+ | Serial.println(" | ||
+ | Serial.println(WiFi.localIP()); | ||
+ | |||
+ | Serial.println(" | ||
+ | udp.begin(localPort); | ||
+ | Serial.print(" | ||
+ | Serial.println(udp.localPort()); | ||
+ | |||
+ | // first ntp server | ||
+ | servernbr = 0; | ||
+ | } | ||
+ | |||
+ | void loop() | ||
+ | { | ||
+ | //get a random server from the pool | ||
+ | |||
+ | WiFi.hostByName(ntpServerName[servernbr], | ||
+ | Serial.print(ntpServerName[servernbr]); | ||
+ | Serial.print(":" | ||
+ | Serial.println(ntpServerIP); | ||
+ | |||
+ | sendNTPpacket(ntpServerIP); | ||
+ | // wait to see if a reply is available | ||
+ | delay(1000); | ||
+ | | ||
+ | int cb = udp.parsePacket(); | ||
+ | if (!cb) { | ||
+ | Serial.println(" | ||
+ | if ( servernbr = 5 ) { | ||
+ | servernbr =0; | ||
+ | } | ||
+ | else { | ||
+ | servernbr++; | ||
+ | } | ||
+ | } | ||
+ | else { | ||
+ | Serial.print(" | ||
+ | Serial.println(cb); | ||
+ | // We've received a packet, read the data from it | ||
+ | udp.read(packetBuffer, | ||
+ | |||
+ | //the timestamp starts at byte 40 of the received packet and is four bytes, | ||
+ | // or two words, long. First, esxtract the two words: | ||
+ | |||
+ | unsigned long highWord = word(packetBuffer[40], | ||
+ | unsigned long lowWord = word(packetBuffer[42], | ||
+ | // combine the four bytes (two words) into a long integer | ||
+ | // this is NTP time (seconds since Jan 1 1900): | ||
+ | unsigned long secsSince1900 = highWord << 16 | lowWord; | ||
+ | Serial.print(" | ||
+ | Serial.println(secsSince1900); | ||
+ | |||
+ | // now convert NTP time into everyday time: | ||
+ | Serial.print(" | ||
+ | // Unix time starts on Jan 1 1970. In seconds, that's 2208988800: | ||
+ | const unsigned long seventyYears = 2208988800UL; | ||
+ | // subtract seventy years: | ||
+ | unsigned long epoch = secsSince1900 - seventyYears; | ||
+ | // print Unix time: | ||
+ | Serial.println(epoch); | ||
+ | |||
+ | |||
+ | // print the hour, minute and second: | ||
+ | // UTC is the time at Greenwich Meridian (GMT) | ||
+ | Serial.print(" | ||
+ | // print the hour (86400 equals secs per day) | ||
+ | Serial.print((epoch | ||
+ | Serial.print(':' | ||
+ | if ( ((epoch % 3600) / 60) < 10 ) { | ||
+ | // In the first 10 minutes of each hour, we'll want a leading ' | ||
+ | Serial.print(' | ||
+ | } | ||
+ | // print the minute (3600 equals secs per minute) | ||
+ | Serial.print((epoch | ||
+ | Serial.print(':' | ||
+ | if ( (epoch % 60) < 10 ) { | ||
+ | // In the first 10 seconds of each minute, we'll want a leading ' | ||
+ | Serial.print(' | ||
+ | } | ||
+ | Serial.println(epoch % 60); // print the second | ||
+ | } | ||
+ | // wait ten seconds before asking for the time again | ||
+ | delay(10000); | ||
+ | } | ||
+ | |||
+ | // send an NTP request to the time server at the given address | ||
+ | void sendNTPpacket(IPAddress& | ||
+ | { | ||
+ | Serial.print(" | ||
+ | Serial.println( address ); | ||
+ | // set all bytes in the buffer to 0 | ||
+ | memset(packetBuffer, | ||
+ | // Initialize values needed to form NTP request | ||
+ | // (see URL above for details on the packets) | ||
+ | packetBuffer[0] = 0b11100011; | ||
+ | packetBuffer[1] = 0; // Stratum, or type of clock | ||
+ | packetBuffer[2] = 6; // Polling Interval | ||
+ | packetBuffer[3] = 0xEC; // Peer Clock Precision | ||
+ | // 8 bytes of zero for Root Delay & Root Dispersion | ||
+ | packetBuffer[12] | ||
+ | packetBuffer[13] | ||
+ | packetBuffer[14] | ||
+ | packetBuffer[15] | ||
+ | |||
+ | // all NTP fields have been given values, now | ||
+ | // you can send a packet requesting a timestamp: | ||
+ | udp.beginPacket(address, | ||
+ | udp.write(packetBuffer, | ||
+ | udp.endPacket(); | ||
+ | } | ||
+ | |||
+ | |||
+ | </ | ||
+ | |||
+ | ==== ESP8266 Wifi Scanner ==== | ||
+ | This sketch demonstrates how to scan WiFi networks. ESP8266 is programmed in access point mode. | ||
+ | All found WiFi networks will be printed in TTY serial window. | ||
+ | |||
+ | <code c > | ||
+ | #include " | ||
+ | |||
+ | void setup() { | ||
+ | Serial.begin(115200); | ||
+ | |||
+ | // Set WiFi to station mode and disconnect | ||
+ | // from an AP if it was previously connected | ||
+ | WiFi.mode(WIFI_STA); | ||
+ | WiFi.disconnect(); | ||
+ | delay(100); | ||
+ | |||
+ | Serial.println(" | ||
+ | } | ||
+ | |||
+ | void loop() { | ||
+ | Serial.println(" | ||
+ | |||
+ | // WiFi.scanNetworks will return the number of networks found | ||
+ | int n = WiFi.scanNetworks(); | ||
+ | Serial.println(" | ||
+ | if (n == 0) | ||
+ | Serial.println(" | ||
+ | else | ||
+ | { | ||
+ | Serial.print(n); | ||
+ | Serial.println(" | ||
+ | for (int i = 0; i < n; ++i) | ||
+ | { | ||
+ | // Print SSID and RSSI for each network found | ||
+ | Serial.print(i + 1); | ||
+ | Serial.print(": | ||
+ | Serial.print(WiFi.SSID(i)); | ||
+ | Serial.print(" | ||
+ | Serial.print(WiFi.RSSI(i)); | ||
+ | Serial.print(" | ||
+ | Serial.println((WiFi.encryptionType(i) == ENC_TYPE_NONE)?" | ||
+ | delay(10); | ||
+ | } | ||
+ | } | ||
+ | Serial.println("" | ||
+ | |||
+ | // Wait a bit before scanning again | ||
+ | delay(5000); | ||
+ | } | ||
+ | |||
+ | </ | ||
+ | |||
+ | ==== ESP32 Wifi Scanner ==== | ||
+ | There are many different development software and tools which can be used for ESP32 programming ((https:// | ||
+ | * Arduino COre ( C++) | ||
+ | * ESP-IDF (Espressif IoT Development Framework) | ||
+ | * Mongoose OS | ||
+ | * MicroPython | ||
+ | * Simba Embedded Programming Platform | ||
+ | * Lua | ||
+ | * JacvaSript | ||
+ | * mruby | ||
+ | * BASIC | ||
+ | |||
+ | Of course, for programming ESP32 We can use all the previously described Arduino examples for sensors and actuators. But in our example, we will focus on programming in ESP-IDF, as this is the native Development Platform for ESP32. A detailed description of the installation of the development environment can be found [[https:// | ||
+ | |||
+ | This example shows how to use the All Channel Scan or Fast Scan to connect to a Wi-Fi network. In the Fast Scan mode, the scan will stop as soon as the first network matching the SSID is found. In this mode, an application can set the threshold for the authentication mode and the Signal strength. Networks that do not meet the threshold requirements will be ignored. In the All Channel Scan mode, the scan will end after all the channels are scanned, and the connection will start with the best network. The networks can be sorted based on Authentication Mode or Signal Strength. The priority for the Authentication mode is: WPA2 > WPA > WEP > Open. | ||
+ | <code c> | ||
+ | #include " | ||
+ | #include " | ||
+ | #include " | ||
+ | #include " | ||
+ | #include " | ||
+ | #include " | ||
+ | |||
+ | /*Set the SSID and Password via "make menuconfig" | ||
+ | #define DEFAULT_SSID CONFIG_WIFI_SSID | ||
+ | #define DEFAULT_PWD CONFIG_WIFI_PASSWORD | ||
+ | |||
+ | #if CONFIG_WIFI_ALL_CHANNEL_SCAN | ||
+ | #define DEFAULT_SCAN_METHOD WIFI_ALL_CHANNEL_SCAN | ||
+ | #elif CONFIG_WIFI_FAST_SCAN | ||
+ | #define DEFAULT_SCAN_METHOD WIFI_FAST_SCAN | ||
+ | #else | ||
+ | #define DEFAULT_SCAN_METHOD WIFI_FAST_SCAN | ||
+ | #endif / | ||
+ | |||
+ | #if CONFIG_WIFI_CONNECT_AP_BY_SIGNAL | ||
+ | #define DEFAULT_SORT_METHOD WIFI_CONNECT_AP_BY_SIGNAL | ||
+ | #elif CONFIG_WIFI_CONNECT_AP_BY_SECURITY | ||
+ | #define DEFAULT_SORT_METHOD WIFI_CONNECT_AP_BY_SECURITY | ||
+ | #else | ||
+ | #define DEFAULT_SORT_METHOD WIFI_CONNECT_AP_BY_SIGNAL | ||
+ | #endif / | ||
+ | |||
+ | #if CONFIG_FAST_SCAN_THRESHOLD | ||
+ | #define DEFAULT_RSSI CONFIG_FAST_SCAN_MINIMUM_SIGNAL | ||
+ | #if CONFIG_EXAMPLE_OPEN | ||
+ | #define DEFAULT_AUTHMODE WIFI_AUTH_OPEN | ||
+ | #elif CONFIG_EXAMPLE_WEP | ||
+ | #define DEFAULT_AUTHMODE WIFI_AUTH_WEP | ||
+ | #elif CONFIG_EXAMPLE_WPA | ||
+ | #define DEFAULT_AUTHMODE WIFI_AUTH_WPA_PSK | ||
+ | #elif CONFIG_EXAMPLE_WPA2 | ||
+ | #define DEFAULT_AUTHMODE WIFI_AUTH_WPA2_PSK | ||
+ | #else | ||
+ | #define DEFAULT_AUTHMODE WIFI_AUTH_OPEN | ||
+ | #endif | ||
+ | #else | ||
+ | #define DEFAULT_RSSI -127 | ||
+ | #define DEFAULT_AUTHMODE WIFI_AUTH_OPEN | ||
+ | #endif / | ||
+ | |||
+ | static const char *TAG = " | ||
+ | |||
+ | static esp_err_t event_handler(void *ctx, system_event_t *event) | ||
+ | { | ||
+ | switch (event-> | ||
+ | case SYSTEM_EVENT_STA_START: | ||
+ | ESP_LOGI(TAG, | ||
+ | ESP_ERROR_CHECK(esp_wifi_connect()); | ||
+ | break; | ||
+ | case SYSTEM_EVENT_STA_GOT_IP: | ||
+ | ESP_LOGI(TAG, | ||
+ | ESP_LOGI(TAG, | ||
+ | | ||
+ | break; | ||
+ | case SYSTEM_EVENT_STA_DISCONNECTED: | ||
+ | ESP_LOGI(TAG, | ||
+ | ESP_ERROR_CHECK(esp_wifi_connect()); | ||
+ | break; | ||
+ | default: | ||
+ | break; | ||
+ | } | ||
+ | return ESP_OK; | ||
+ | } | ||
+ | |||
+ | /* Initialize Wi-Fi as sta and set scan method */ | ||
+ | static void wifi_scan(void) | ||
+ | { | ||
+ | tcpip_adapter_init(); | ||
+ | ESP_ERROR_CHECK(esp_event_loop_init(event_handler, | ||
+ | |||
+ | wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT(); | ||
+ | ESP_ERROR_CHECK(esp_wifi_init(& | ||
+ | ESP_LOGI(TAG, | ||
+ | ESP_LOGI(TAG, | ||
+ | wifi_config_t wifi_config = { | ||
+ | .sta = { | ||
+ | .ssid = DEFAULT_SSID, | ||
+ | .password = DEFAULT_PWD, | ||
+ | .scan_method = DEFAULT_SCAN_METHOD, | ||
+ | .sort_method = DEFAULT_SORT_METHOD, | ||
+ | .threshold.rssi = DEFAULT_RSSI, | ||
+ | .threshold.authmode = DEFAULT_AUTHMODE, | ||
+ | }, | ||
+ | }; | ||
+ | ESP_ERROR_CHECK(esp_wifi_set_mode(WIFI_MODE_STA)); | ||
+ | ESP_ERROR_CHECK(esp_wifi_set_config(ESP_IF_WIFI_STA, | ||
+ | ESP_ERROR_CHECK(esp_wifi_start()); | ||
+ | } | ||
+ | |||
+ | void app_main() | ||
+ | { | ||
+ | // Initialize NVS | ||
+ | esp_err_t ret = nvs_flash_init(); | ||
+ | if (ret == ESP_ERR_NVS_NO_FREE_PAGES) { | ||
+ | ESP_ERROR_CHECK(nvs_flash_erase()); | ||
+ | ret = nvs_flash_init(); | ||
+ | } | ||
+ | ESP_ERROR_CHECK( ret ); | ||
+ | |||
+ | wifi_scan(); | ||
+ | } | ||
+ | </ | ||
+ | |||
+ | To properly set up Station mode, it is necessary to enter SSID and password. To enter these values, before compiling the program, run the command: | ||
+ | |||
+ | <code c> | ||
+ | make menuconfig | ||
+ | </ | ||
+ | |||
+ | and then | ||
+ | |||
+ | <code c> | ||
+ | make all | ||
+ | </ | ||
+ | |||
+ | or | ||
+ | |||
+ | <code c> | ||
+ | make flash | ||
+ | </ | ||
+ | |||
+ | |||
+ | === === | ||
+ | <box # | ||
+ | <box # | ||
+ | === ESP Application Layer === | ||
+ | <box # | ||
+ | <box # | ||
+ | |||
+ | ESP application layer may offer simplified a vast number of services as known from the PC world and the Internet yet. The limitation is the RAM size, storage, number of concurrent connections and limited CPU capabilities. Response routines should be kept simple as ESP8266 is single-threaded and uses timers and interrupt system to handle WiFi tasks in the background. | ||
+ | == ESP8266 Samples == | ||
+ | Below we present a number of samples, introducing programming of the various scenarios with ESP8266. | ||
+ | |||
+ | **ESP8266 Web Server Sample** | ||
+ | |||
+ | This example can be compiled in Arduino IDE. It allows through the website to change the output state of PIN 4 and PIN 5 ((http:// | ||
+ | <code c> | ||
+ | const char* ssid = ".. put here your own SSID name ..."; | ||
+ | const char* password = ".. put here your SSID password.. "; | ||
+ | </ | ||
+ | Now please check in the serial console the ESp8266 IP number and connect with any browser to address: http:// | ||
+ | |||
+ | <code c > | ||
+ | // Load Wi-Fi library | ||
+ | #include < | ||
+ | |||
+ | // Replace with your network credentials | ||
+ | const char* ssid = ".. put here your own SSID name ..."; | ||
+ | const char* password = ".. put here your SSID password.. "; | ||
+ | |||
+ | // Set web server port number to 80 | ||
+ | WiFiServer server(80); | ||
+ | |||
+ | // Variable to store the HTTP request | ||
+ | String header; | ||
+ | |||
+ | // Auxiliar variables to store the current output state | ||
+ | String gpio5State = " | ||
+ | String gpio4State = " | ||
+ | |||
+ | // Assign output variables to GPIO pins | ||
+ | const int gpiopin5 = 5; | ||
+ | const int gpiopin4 = 4; | ||
+ | |||
+ | void setup() { | ||
+ | Serial.begin(115200); | ||
+ | // Initialize the output variables as outputs | ||
+ | pinMode(gpiopin5, | ||
+ | pinMode(gpiopin4, | ||
+ | // Set outputs to LOW | ||
+ | digitalWrite(gpiopin5, | ||
+ | digitalWrite(gpiopin4, | ||
+ | |||
+ | // Connect to Wi-Fi network with SSID and password | ||
+ | Serial.print(" | ||
+ | Serial.println(ssid); | ||
+ | WiFi.begin(ssid, | ||
+ | while (WiFi.status() != WL_CONNECTED) { | ||
+ | delay(500); | ||
+ | Serial.print(" | ||
+ | } | ||
+ | // Print local IP address and start web server | ||
+ | Serial.println("" | ||
+ | Serial.println(" | ||
+ | Serial.println(" | ||
+ | Serial.println(WiFi.localIP()); | ||
+ | server.begin(); | ||
+ | } | ||
+ | |||
+ | void loop(){ | ||
+ | WiFiClient client = server.available(); | ||
+ | |||
+ | if (client) { // If a new client connects, | ||
+ | Serial.println(" | ||
+ | String currentLine = ""; | ||
+ | while (client.connected()) { // loop while the client' | ||
+ | if (client.available()) { // if there' | ||
+ | char c = client.read(); | ||
+ | Serial.write(c); | ||
+ | header += c; | ||
+ | if (c == ' | ||
+ | // if the current line is blank, you got two newline characters in a row. | ||
+ | // that's the end of the client HTTP request, so send a response: | ||
+ | if (currentLine.length() == 0) { | ||
+ | // HTTP headers always start with a response code | ||
+ | // (e.g. HTTP/1.1 200 OK) | ||
+ | // and a content-type so the client knows what's coming, | ||
+ | // then a blank line: | ||
+ | client.println(" | ||
+ | client.println(" | ||
+ | client.println(" | ||
+ | client.println(); | ||
+ | | ||
+ | // turns the GPIOs on and off | ||
+ | if (header.indexOf(" | ||
+ | Serial.println(" | ||
+ | gpio5State = " | ||
+ | digitalWrite(gpiopin5, | ||
+ | } else if (header.indexOf(" | ||
+ | Serial.println(" | ||
+ | gpio5State = " | ||
+ | digitalWrite(gpiopin5, | ||
+ | } else if (header.indexOf(" | ||
+ | Serial.println(" | ||
+ | gpio4State = " | ||
+ | digitalWrite(gpiopin4, | ||
+ | } else if (header.indexOf(" | ||
+ | Serial.println(" | ||
+ | gpio4State = " | ||
+ | digitalWrite(gpiopin4, | ||
+ | } | ||
+ | | ||
+ | // Display the HTML web page | ||
+ | client.println("< | ||
+ | client.println("< | ||
+ | | ||
+ | client.println("< | ||
+ | // CSS to style the on/off buttons | ||
+ | // Feel free to change the background-color and | ||
+ | // font-size attributes to fit your preferences | ||
+ | client.println("< | ||
+ | inline-block; | ||
+ | client.println(" | ||
+ | border: none; color: white; padding: 16px 40px;" | ||
+ | client.println(" | ||
+ | font-size: 30px; margin: 2px; cursor: pointer; | ||
+ | client.println(" | ||
+ | | ||
+ | // Web Page Heading | ||
+ | client.println("< | ||
+ | | ||
+ | // Display current state, and ON/OFF buttons for GPIO 5 | ||
+ | client.println("< | ||
+ | // If the output5State is off, it displays the ON button | ||
+ | if (gpio5State==" | ||
+ | client.println("< | ||
+ | | ||
+ | } else { | ||
+ | client.println("< | ||
+ | | ||
+ | } | ||
+ | |||
+ | // Display current state, and ON/OFF buttons for GPIO 4 | ||
+ | client.println("< | ||
+ | // If the output4State is off, it displays the ON button | ||
+ | if (gpio4State==" | ||
+ | client.println("< | ||
+ | | ||
+ | } else { | ||
+ | client.println("< | ||
+ | | ||
+ | } | ||
+ | client.println("</ | ||
+ | | ||
+ | // The HTTP response ends with another blank line | ||
+ | client.println(); | ||
+ | // Break out of the while loop | ||
+ | break; | ||
+ | } else { // if you got a newline, then clear currentLine | ||
+ | currentLine = ""; | ||
+ | } | ||
+ | } else if (c != ' | ||
+ | // else but a carriage return character, | ||
+ | currentLine += c; // add it to the end of the currentLine | ||
+ | } | ||
+ | } | ||
+ | } | ||
+ | // Clear the header variable | ||
+ | header = ""; | ||
+ | // Close the connection | ||
+ | client.stop(); | ||
+ | Serial.println(" | ||
+ | Serial.println("" | ||
+ | } | ||
+ | } | ||
+ | </ | ||
+ | |||
+ | After connecting with web browser to ESP8266 there will be such web page (figure {{ref> | ||
+ | <figure esp8266page> | ||
+ | {{ : | ||
+ | < | ||
+ | </ | ||
+ | |||
+ | == ESP32 Samples == | ||
+ | |||
+ | **ESP32 "Hello World" | ||
+ | |||
+ | This is simple program printing "Hello World" and it is written in Espressif IoT Development Framework | ||
+ | <code c> | ||
+ | #include < | ||
+ | #include " | ||
+ | #include " | ||
+ | #include " | ||
+ | #include " | ||
+ | |||
+ | void app_main() | ||
+ | { | ||
+ | printf(" | ||
+ | |||
+ | /* Print chip information */ | ||
+ | esp_chip_info_t chip_info; | ||
+ | esp_chip_info(& | ||
+ | printf(" | ||
+ | chip_info.cores, | ||
+ | (chip_info.features & CHIP_FEATURE_BT) ? "/ | ||
+ | (chip_info.features & CHIP_FEATURE_BLE) ? "/ | ||
+ | |||
+ | printf(" | ||
+ | |||
+ | printf(" | ||
+ | (chip_info.features & CHIP_FEATURE_EMB_FLASH) ? | ||
+ | " | ||
+ | |||
+ | for (int i = 10; i >= 0; i--) { | ||
+ | printf(" | ||
+ | vTaskDelay(1000 / portTICK_PERIOD_MS); | ||
+ | } | ||
+ | printf(" | ||
+ | fflush(stdout); | ||
+ | esp_restart(); | ||
+ | } | ||
+ | |||
+ | </ | ||
+ | |||
+ | |||
+ | **ESP32 Web Server** | ||
+ | |||
+ | This example of ESP32 programming in Arduino and shows how to implement simple www server. | ||
+ | |||
+ | First we do a little initialisation | ||
+ | |||
+ | < | ||
+ | //################# | ||
+ | #include < | ||
+ | #include < | ||
+ | #include < | ||
+ | //################ | ||
+ | |||
+ | String webpage = ""; | ||
+ | const char* ssid = " | ||
+ | const char* password | ||
+ | |||
+ | int status = WL_IDLE_STATUS; | ||
+ | int curr_index; | ||
+ | String SensorStatusBME; | ||
+ | |||
+ | // Site's Main Title | ||
+ | String siteheading | ||
+ | // Sub-heading for all pages | ||
+ | String subheading | ||
+ | // Appears on the tabe of a Web Browser | ||
+ | String sitetitle | ||
+ | // A foot note e.g. "My Web Site" | ||
+ | String yourfootnote | ||
+ | // Version of your Website | ||
+ | String siteversion | ||
+ | </ | ||
+ | |||
+ | Then we must implement the main www server activities. Mind, to access the server from outside of your network WiFi (LAN) e.g. on port 80 when in NAT mode, add a rule on your router that forwards a connection request to http:// | ||
+ | |||
+ | <code c> | ||
+ | ESP32WebServer server(80); | ||
+ | void setup() | ||
+ | { | ||
+ | Serial.begin(115200); | ||
+ | curr_index = 1; | ||
+ | |||
+ | time_to_measure = millis(); | ||
+ | |||
+ | StartWiFi(ssid, | ||
+ | StartTime(); | ||
+ | // | ||
+ | Serial.println(" | ||
+ | // If the user types at their browser | ||
+ | // http:// | ||
+ | // to user_input, you get values for your program... | ||
+ | server.on("/", | ||
+ | // If the user types at their browser | ||
+ | // http:// | ||
+ | // is passed here and then to the homepage, etc | ||
+ | server.on("/ | ||
+ | |||
+ | // If the user types something that is not supported, say so | ||
+ | server.onNotFound(handleNotFound); | ||
+ | // Start the webserver | ||
+ | server.begin(); | ||
+ | } | ||
+ | |||
+ | |||
+ | void handleNotFound() { | ||
+ | String message = "The request entered could not be found, | ||
+ | please try again with a different option\n"; | ||
+ | server.send(404, | ||
+ | } | ||
+ | |||
+ | void homepage() { | ||
+ | append_HTML_header(); | ||
+ | webpage += "<P class=' | ||
+ | webpage += "<p class=' | ||
+ | webpage += "This is sample webpage"; | ||
+ | webpage += "</ | ||
+ | webpage += "< | ||
+ | String Uptime = (String(millis() / 1000 / 60 / 60)) + ":"; | ||
+ | Uptime += (((millis() / 1000 / 60 % 60) < 10) ? " | ||
+ | | ||
+ | | ||
+ | Uptime += ((millis() / 1000 % 60) < 10) ? " | ||
+ | | ||
+ | | ||
+ | webpage += "< | ||
+ | append_HTML_footer(); | ||
+ | server.send(200, | ||
+ | } | ||
+ | |||
+ | void page1() { | ||
+ | |||
+ | append_HTML_header(); | ||
+ | webpage += "< | ||
+ | webpage += "<P class=' | ||
+ | webpage += "<p class=' | ||
+ | webpage += "This is sample 1 page"; | ||
+ | webpage += "</ | ||
+ | append_HTML_footer(); | ||
+ | server.send(200, | ||
+ | } | ||
+ | |||
+ | </ | ||
+ | |||
+ | next we must start Wifi : | ||
+ | < | ||
+ | void StartWiFi(const char* ssid, const char* password) { | ||
+ | int connAttempts = 0; | ||
+ | Serial.print(F(" | ||
+ | WiFi.begin(ssid, | ||
+ | |||
+ | status = WiFi.status(); | ||
+ | |||
+ | while (status != WL_CONNECTED ) { | ||
+ | Serial.print(" | ||
+ | // wait 10 second for re-trying | ||
+ | delay(10000); | ||
+ | status = WiFi.status(); | ||
+ | Serial.println(status); | ||
+ | if (connAttempts > 5) { | ||
+ | Serial.println(" | ||
+ | // printWiFiStatus(); | ||
+ | } | ||
+ | connAttempts++; | ||
+ | } | ||
+ | Serial.print(F(" | ||
+ | Serial.println(WiFi.localIP()); | ||
+ | } | ||
+ | </ | ||
+ | |||
+ | and last step is to implement main loop function: | ||
+ | |||
+ | < | ||
+ | void loop() { | ||
+ | | ||
+ | delay( 2000 ); | ||
+ | server.handleClient(); | ||
+ | |||
+ | } | ||
+ | |||
+ | </ | ||
+ | === === | ||
+ | <box # | ||
+ | <box # | ||
+ | === ESP32 Parallel Programming === | ||
+ | <box # | ||
+ | <box # | ||
+ | |||
+ | As it is known, some of the microcontrollers, | ||
+ | |||
+ | At the time while this chapter is being written, the simplest way of developing a parallel code on ESP32 is via using FreeRTOS™ ((https:// | ||
+ | The following code chunks explain how to apply the most useful parallel programming features. | ||
+ | |||
+ | Let's start with an example of blinking LED and Text output (based on material found here ((https:// | ||
+ | |||
+ | The first task is task1, that simply outputs a string "Hi there!" | ||
+ | |||
+ | <code c> | ||
+ | #include < | ||
+ | #include " | ||
+ | #include " | ||
+ | #include " | ||
+ | #include " | ||
+ | |||
+ | #define BLINK_GPIO 13 | ||
+ | | ||
+ | void task1_SayHi(void * parameters) | ||
+ | { | ||
+ | | ||
+ | { | ||
+ | | ||
+ | | ||
+ | } | ||
+ | } | ||
+ | </ | ||
+ | |||
+ | < | ||
+ | |||
+ | * //# | ||
+ | * //#define// BLINK_GPIO 13 -- defines output pin that will be used to switch on or off the LED. | ||
+ | * // | ||
+ | |||
+ | </ | ||
+ | |||
+ | The second task is to bilk a LED with a period of 2 seconds (1 second on, 1 second off): | ||
+ | |||
+ | <code c> | ||
+ | void task2_BlinkLED(void * parameters) | ||
+ | { | ||
+ | |||
+ | gpio_pad_select_gpio(BLINK_GPIO); | ||
+ | gpio_set_direction(BLINK_GPIO, | ||
+ | while(1) { | ||
+ | /*Sets the LED low for one second*/ | ||
+ | gpio_set_level(BLINK_GPIO, | ||
+ | vTaskDelay(1000 / portTICK_RATE_MS); | ||
+ | | ||
+ | /*Sets the LED high for one second*/ | ||
+ | gpio_set_level(BLINK_GPIO, | ||
+ | vTaskDelay(1000 / portTICK_RATE_MS); | ||
+ | } | ||
+ | } | ||
+ | </ | ||
+ | |||
+ | Once both task functions are defined, they can be executed simultaneously: | ||
+ | |||
+ | <code c> | ||
+ | void app_main() | ||
+ | { | ||
+ | nvs_flash_init(); | ||
+ | xTaskCreate(& | ||
+ | xTaskCreate(& | ||
+ | } | ||
+ | </ | ||
+ | |||
+ | < | ||
+ | |||
+ | * // | ||
+ | * // | ||
+ | |||
+ | </ | ||
+ | |||
+ | <note tip> | ||
+ | In fact, the code does not run in parallel physically, it uses the full speed of the ESP32 that is far beyond human perception speed and shares the computation time between both tasks. Therefore for the human, it seems to be running in parallel. Each of the tasks uses Idle (defined by // | ||
+ | </ | ||
+ | |||
+ | To run the code physically in parallel it is necessary to assign task explicitly to the particular core, which requires a slight modification of the //main()// function: | ||
+ | |||
+ | <code c> | ||
+ | void app_main() | ||
+ | { | ||
+ | nvs_flash_init(); | ||
+ | xTaskCreatePinnedToCore(& | ||
+ | xTaskCreatePinnedToCore(& | ||
+ | } | ||
+ | </ | ||
+ | |||
+ | < | ||
+ | |||
+ | * // | ||
+ | |||
+ | </ | ||
+ | |||
+ | While ESP32 provide two computing nodes, other devices like particular serial port or other peripherals are only single devices. In some cases, it might be needed to access those devices by multiple processes in a way that does not disturb the others. In a terminology of parallel programming, | ||
+ | To explain the concept of resource sharing here a simple binary-semaphore example is provided. Example uses two SayHi tasks to share the same output device: | ||
+ | |||
+ | Since we need to define a semaphore at the beginning a setup function is also needed: | ||
+ | |||
+ | <code c> | ||
+ | #include < | ||
+ | #include " | ||
+ | #include " | ||
+ | #include " | ||
+ | #include " | ||
+ | |||
+ | SemaphoreHandle_t xSemaphore = NULL; | ||
+ | |||
+ | void setup() | ||
+ | { | ||
+ | vSemaphoreCreateBinary( xSemaphore ); | ||
+ | } | ||
+ | </ | ||
+ | |||
+ | Now it is possible to define the task functions and modify them in a way they use the same resource | ||
+ | |||
+ | <code c> | ||
+ | void task1_SayHi(void * parameters) | ||
+ | { | ||
+ | | ||
+ | { | ||
+ | / | ||
+ | If the semaphore is available it is taken / blocked */ | ||
+ | if( xSemaphoreTake( xSemaphore, ( TickType_t ) 100 ) == pdTRUE ) | ||
+ | { | ||
+ | printf(" | ||
+ | vTaskDelay(100 / portTICK_RATE_MS); | ||
+ | xSemaphoreGive( xSemaphore ); | ||
+ | } | ||
+ | else | ||
+ | { | ||
+ | // | ||
+ | | ||
+ | } | ||
+ | } | ||
+ | |||
+ | void task2_SayHi(void * parameters) | ||
+ | { | ||
+ | | ||
+ | { | ||
+ | / | ||
+ | If the semaphore is available it is taken / blocked */ | ||
+ | if( xSemaphoreTake( xSemaphore, ( TickType_t ) 100 ) == pdTRUE ) | ||
+ | { | ||
+ | printf(" | ||
+ | vTaskDelay(100 / portTICK_RATE_MS); | ||
+ | xSemaphoreGive( xSemaphore ); | ||
+ | } | ||
+ | else | ||
+ | { | ||
+ | // | ||
+ | | ||
+ | } | ||
+ | } | ||
+ | </ | ||
+ | |||
+ | Now both of the tasks are ready to be executed on the same or different cores as explained previously. | ||
+ | |||
+ | <note tip> | ||
+ | |||
+ | ===== ===== | ||
+ | <box # | ||
+ | <box # | ||
+ | ===== Raspberry Pi Overview ===== | ||
+ | <box # | ||
+ | <box # | ||
+ | |||
+ | Raspberry Pi (referred as RPi or RPI) and its clones, i.e. Orange Pi, Banana Pi, Ordroid, Cubie, Olimex, are the class of devices located somewhere between low constraint IoT boards and regular PC/Mac machines. | ||
+ | <note tip> | ||
+ | Those devices technically are very close to smartphones and are far away from energy-efficient IoT solutions powered by a single battery that lasts for weeks or even years. | ||
+ | They need DC, usually 5 or 12V and about 2-3W total, with external power adapter. It is still far less than even most efficient ultrabooks or PCs, requiring some 50-90W PSUs. They also use an operating system booted from storage like regular PCs - usually from flashed MicroSD card or embedded eMMC flash. The OS is mostly Linux based, but there do exist Microsoft Windows for certified Raspberry Pi devices. It is how this class of devices differ from, i.e. Arduino, where software is in the SoC model. The RPi and clones are holding a one-board solution that includes a processor, memory, storage slot, USB and networking. Many devices also offer hardware-based graphics acceleration, | ||
+ | What is pretty similar to the low-power, constrained IoT boards, RPi and clones offer GPIO, and you can connect various sensors and expansion boards (called here " | ||
+ | |||
+ | What is much different from low constrained IoT devices is that they offer at least a command terminal you can connect to, and also most boards offer a capability to connect it to the external display via HDMI, analogue output or dedicated connector for LCD. They also provide the ability to interact with HID devices like regular keyboards, mouses, via USB but also wireless, i.e. using a Bluetooth connection. Of course, those features are dependent on operating systems. | ||
+ | Manufacturers usually are trying to keep those development boards as small as possible, and it is a case that among high-end devices they also offer some constrained solution yet usually 50 % smaller in size and power consumption (i.e. RPi zero). Many boards also offer dedicated camera connector. | ||
+ | |||
+ | Being so far from the low-power, constrained IoT devices does not exclude them from IoT devices, however. They find their application everywhere, when there is a need for higher processing resources (i.e. voice recognition), | ||
+ | |||
+ | On the other hand, most modern representatives of those devices are powered with multicore processors and large RAM and are powerful enough to replace the desktop computer in daily operations like web browsing, multimedia playback, software development and so on. | ||
+ | |||
+ | * " | ||
+ | |||
+ | * " | ||
+ | |||
+ | * " | ||
+ | |||
+ | * " | ||
+ | |||
+ | * " | ||
+ | |||
+ | * " | ||
+ | ==== ==== | ||
+ | <box # | ||
+ | <box # | ||
+ | ==== Raspberry Pi General Information ==== | ||
+ | <box # | ||
+ | <box # | ||
+ | |||
+ | The Raspberry Pi is a series of small single-board computers developed in the UK by the Raspberry Pi Foundation to promote modern computer science in schools and developing electronic communities. Adding the 40-pin GPIO connector to the computer board allows developers not only improving their programming skills but also open them new horizons in controlling processes and devices not available for desktop computers. According to the Raspberry Pi Foundation, the entire boards' | ||
+ | The first generation of this new board type was developed and then released in February 2012 -- **Raspberry Pi Model B**. Each Raspberry Pi board contains hardware modules which together makes it fully usable PC like a computer which size fits the typical credit card (85/56 mm) size and small power consumption < 3.5 W. This makes this kind of single board computers one of the most popular in developers community. For today there exist thousands of hardware implementation projects available for users who want to learn the modern hardware and software controlling units within their projects. The general Raspberry Pi features are listed below. | ||
+ | |||
+ | === Hardware === | ||
+ | Hardware boards (depending on the manufactured model) contains interfaces: | ||
+ | |||
+ | === Processor === | ||
+ | The first Raspberry Pi 2 models use the 900 MHz Broadcom BCM2836 SoC 32-bit quad-core ARM Cortex-A7 processor, with shared 256 KB L2 cache. After this earlier models, the Raspberry Pi 2 V1.2 has been upgraded to a Broadcom BCM2837 SoC equipped with a 1.2 GHz 64-bit quad-core ARM Cortex-A53 processor. Latest Raspberry Pi 3 series uses the same SoC. They use the Broadcom BCM2837 SoC with a 1.2 GHz 64-bit quad-core ARM Cortex-A53 processor, equipped with 512 KB shared L2 cache. The Raspberry Pi 3B+ uses the same processor (BCM2837B0) but running at 1.4 GHz. Next Raspberry Pi generations are going to be more and more powerful, but their power consumption is still rising to force developers to use CPU and GPU heatsinks. | ||
+ | |||
+ | === RAM === | ||
+ | Older B board models were designed with 128 MB RAM which was by default allocated between the GPU and CPU. The Model B (including Model A) release the RAM was extended to 256 MB split to there regions. The default split was 192 MB (RAM for CPU), which is sufficient for standalone 1080p video decoding, or for 3D modelling. Models B with 512 MB RAM initially, memory was split to files released (arm256_start.elf, | ||
+ | |||
+ | === Networking === | ||
+ | The Model A, A+ and Pi Zero have no dedicated Ethernet interface and can be connected to a network using an external USB Ethernet or WiFi adapter. In Models B and B+, the Ethernet port is built-in to the USB Ethernet adapter using the SMSC LAN9514 chip. The Raspberry Pi 3 and Pi Zero W (wireless) models are equipped with 2.4 GHz WiFi 802.11n (150 Mbit/s) and Bluetooth 4.1 (24 Mbit/s) based on Broadcom BCM43438 FullMAC chip. The Raspberry Pi 3 also has a 10/100 Ethernet port. | ||
+ | |||
+ | === Peripherals === | ||
+ | The Raspberry Pi may be controlled with any generic USB computer keyboard and mouse. It can also use USB storage, USB to MIDI converters, and virtually any other device/ | ||
+ | Other peripherals can be attached through the various pins and connectors on the surface of the Raspberry Pi. | ||
+ | |||
+ | === Video === | ||
+ | The video controller supports standard modern TV resolutions, | ||
+ | |||
+ | === Real-Time Clock === | ||
+ | None of the current Raspberry Pi models is equipped with a built-in real-time clock. Developers which needs the real clock time in their project can retrieve the time from a network time server (NTP) or use the external RTC module connected to the board via SPI or I²C interface. To save the file system consistency of time, the Raspberry Pi automatically saves the time on shutdown, and reload it time at boot. One of the best RTC solutions for keeping the proper boards time is to use the I²C DS1307 chip containing hardware clock with battery power supply. | ||
+ | |||
+ | === Specification === | ||
+ | < | ||
+ | < | ||
+ | ^ Version | ||
+ | ^ ::: | **RPi 1 Model A** | **RPi 1 Model A+** | **RPi 3 Model A+** | | ||
+ | ^Release date |2/ | ||
+ | ^Target price (USD) |25|20|25| | ||
+ | ^Instruction set |ARMv6Z (32-bit)||ARMv8 (64-bit)| | ||
+ | ^SoC |Broadcom BCM2835||Broadcom BCM2837B0| | ||
+ | ^FPU |VFPv2; NEON not supported||VFPv4 + NEON| | ||
+ | ^CPU |1× ARM1176JZF-S 700 MHz||4× Cortex-A53 1.4 GHz| | ||
+ | ^GPU | Broadcom VideoCore IV @ 250 MHz (BCM2837: 3D part of GPU @ 300 MHz, video part of GPU @ 400 MHz) ||| | ||
+ | ^ ::: | OpenGL ES 2.0 (BCM2835, BCM2836: 24 GFLOPS / BCM2837: 28.8 GFLOPS) | ||
+ | ^ ::: | MPEG-2 and VC-1 (with license), 1080p30 H.264/ | ||
+ | ^Memory (SDRAM) | ||
+ | ^USB 2.0 ports |1 (direct from BCM2835 chip)|| | ||
+ | ^ ::: | ::: | ::: | ::: | | ||
+ | ^ ::: | ::: | ::: | ::: | | ||
+ | ^Video input | 15-pin MIPI camera interface (CSI) connector, used with the Raspberry Pi camera or Raspberry Pi NoIR camera | ||
+ | ^Video outputs | ||
+ | ^Audio inputs | ||
+ | ^Audio outputs | ||
+ | ^On-board storage | ||
+ | ^On-board network | ||
+ | ^ ::: | ::: | ::: | ::: | | ||
+ | ^ ::: | ::: | ::: | ::: | | ||
+ | ^Low-level peripherals | ||
+ | ^ ::: | ::: | ::: | ::: | | ||
+ | ^ ::: | ::: | ::: | ::: | | ||
+ | ^ ::: | ::: | ::: | ::: | | ||
+ | ^Power ratings | ||
+ | ^Power source | ||
+ | ^Size |85.60 mm × 56.5 mm (3.370 in × 2.224 in), excluding protruding connectors|65 mm × 56.5 mm × 10 mm (2.56 in × 2.22 in × 0.39 in), same as HAT board|65 mm x 56.5 mm| | ||
+ | ^Weight | ||
+ | ^Console | ||
+ | ^Generation | ||
+ | ^Obsolescence | ||
+ | ^ | ::: | ::: | ::: | | ||
+ | ^Statement | ||
+ | ^Type ^ **Model A** ^^| | ||
+ | </ | ||
+ | |||
+ | < | ||
+ | < | ||
+ | ^ Version | ||
+ | ^ ::: | **RPi 1 Model B** | **RPi 1 Model B+** | **RPi 2 Model B** | **RPi 2 Model B v1.2** | ||
+ | ^Release date |April–June 2012|7/ | ||
+ | ^Target price (USD) |35|25|35|||| | ||
+ | ^Instruction set |ARMv6Z (32-bit)||ARMv7-A (32-bit)|ARMv8-A (64/ | ||
+ | ^SoC |Broadcom BCM2835||Broadcom BCM2836|Broadcom BCM2837||Broadcom BCM2837B0| | ||
+ | ^FPU |VFPv2; NEON not supported||VFPv3 + NEON|VFPv4 + NEON||| | ||
+ | ^CPU |1× ARM1176JZF-S 700 MHz||4× Cortex-A7 900 MHz|4× Cortex-A53 900 MHz|4× Cortex-A53 1.2 GHz|4× Cortex-A53 1.4 GHz| | ||
+ | ^GPU | Broadcom VideoCore IV @ 250 MHz (BCM2837: 3D part of GPU @ 300 MHz, video part of GPU @ 400 MHz) |||||| | ||
+ | ^ ::: | OpenGL ES 2.0 (BCM2835, BCM2836: 24 GFLOPS / BCM2837: 28.8 GFLOPS) | ||
+ | ^ ::: | MPEG-2 and VC-1 (with license), 1080p30 H.264/ | ||
+ | ^Memory (SDRAM) | ||
+ | ^USB 2.0 ports |2 (via on-board 3-port USB hub)|4 (via on-board 5-port USB hub)||||| | ||
+ | ^ ::: | ::: | ::: | ::: | ::: | ::: | ::: | | ||
+ | ^ ::: | ::: | ::: | ::: | ::: | ::: | ::: | | ||
+ | ^Video input | 15-pin MIPI camera interface (CSI) connector, used with the Raspberry Pi camera or Raspberry Pi NoIR camera | ||
+ | ^Video outputs | ||
+ | ^Audio inputs | ||
+ | ^Audio outputs | ||
+ | ^On-board storage | ||
+ | ^On-board network | ||
+ | ^ ::: | ::: | ::: | ::: | ::: |802.11b/ | ||
+ | ^ ::: | ::: | ::: | ::: | ::: |Bluetooth 4.1 BLE|Bluetooth 4.2 LS BLE| | ||
+ | ^Low-level peripherals | ||
+ | ^ ::: | | ::: | ::: | ::: | ::: | ::: | | ||
+ | ^ ::: |An additional 4× GPIO are available on the P5 pad if the user is willing to make solder connections| ::: | ::: | ::: | ::: | ::: | | ||
+ | ^ ::: | | ::: | ::: | ::: | ::: | ::: | | ||
+ | ^Power ratings | ||
+ | ^Power source | ||
+ | ^Size |85.60 mm × 56.5 mm (3.370 in × 2.224 in), excluding protruding connectors||||85.60 mm × 56.5 mm × 17 mm (3.370 in × 2.224 in × 0.669 in)|| | ||
+ | ^Weight | ||
+ | ^Console | ||
+ | ^Generation | ||
+ | ^Obsolescence | ||
+ | ^ | ::: | ::: | ::: | ::: | ::: | ::: | | ||
+ | ^Statement | ||
+ | ^Type ^ **Model B** ^^^^^| | ||
+ | |||
+ | </ | ||
+ | |||
+ | < | ||
+ | < | ||
+ | ^ Version | ||
+ | ^ ::: | **Compute Module 1** | **Compute Module 3** | **Compute Module 3 lite** | ||
+ | ^Release date |4/ | ||
+ | ^Target price (USD) |$30 (in batches of 100)|30|25|| | ||
+ | ^Instruction set |ARMv6Z (32-bit)|ARMv8-A (64/ | ||
+ | ^SoC |Broadcom BCM2835|Broadcom BCM2837||Broadcom BCM2837B0| | ||
+ | ^FPU |VFPv2; NEON not supported|VFPv4 + NEON||| | ||
+ | ^CPU |1× ARM1176JZF-S 700 MHz|4× Cortex-A53 1.2 GHz||| | ||
+ | ^GPU | Broadcom VideoCore IV @ 250 MHz (BCM2837: 3D part of GPU @ 300 MHz, video part of GPU @ 400 MHz) |||| | ||
+ | ^ ::: | OpenGL ES 2.0 (BCM2835, BCM2836: 24 GFLOPS / BCM2837: 28.8 GFLOPS) | ||
+ | ^ ::: | MPEG-2 and VC-1 (with license), 1080p30 H.264/ | ||
+ | ^Memory (SDRAM) | ||
+ | ^USB 2.0 ports |1 (direct from BCM2835 chip)|1 (direct from BCM2837 chip)||| | ||
+ | ^ ::: | ::: | ::: | ::: | ::: | | ||
+ | ^ ::: | ::: | ::: | ::: | ::: | | ||
+ | ^Video input |2× MIPI camera interface (CSI)||| | | ||
+ | ^Video outputs | ||
+ | ^Audio inputs | ||
+ | ^Audio outputs | ||
+ | ^On-board storage | ||
+ | ^On-board network | ||
+ | ^ ::: | ::: | ::: | ::: | ::: | | ||
+ | ^ ::: | ::: | ::: | ::: | ::: | | ||
+ | ^Low-level peripherals | ||
+ | ^ ::: | ::: | ::: | ::: | ::: | | ||
+ | ^ ::: | ::: | ::: | ::: | ::: | | ||
+ | ^ ::: | ::: | ::: | ::: | ::: | | ||
+ | ^Power ratings | ||
+ | ^Power source | ||
+ | ^Size |67.6 mm × 30 mm (2.66 in × 1.18 in)|67.6 mm × 31 mm (2.66 in × 1.22 in)||| | ||
+ | ^Weight | ||
+ | ^Console | ||
+ | ^Generation | ||
+ | ^Obsolescence | ||
+ | ^ | ::: | ::: | ::: | ::: | | ||
+ | ^Statement | ||
+ | ^Type ^ **Compute Module%%*%%** | ||
+ | |||
+ | </ | ||
+ | |||
+ | < | ||
+ | < | ||
+ | ^ Version | ||
+ | ^ ::: | **RPi Zero PCB v1.2** | ||
+ | ^Release date |11/ | ||
+ | ^Target price (USD) |5||10| | ||
+ | ^Instruction set |ARMv6Z (32-bit)||| | ||
+ | ^SoC |Broadcom BCM2835||| | ||
+ | ^FPU |VFPv2; NEON not supported||| | ||
+ | ^CPU |1× ARM1176JZF-S 1 GHz||| | ||
+ | ^GPU | Broadcom VideoCore IV @ 250 MHz (BCM2837: 3D part of GPU @ 300 MHz, video part of GPU @ 400 MHz) ||| | ||
+ | ^ ::: | OpenGL ES 2.0 (BCM2835, BCM2836: 24 GFLOPS / BCM2837: 28.8 GFLOPS) | ||
+ | ^ ::: | MPEG-2 and VC-1 (with license), 1080p30 H.264/ | ||
+ | ^Memory (SDRAM) | ||
+ | ^USB 2.0 ports |1 Micro-USB (direct from BCM2835 chip)||| | ||
+ | ^ ::: | ::: | ::: | ::: | | ||
+ | ^ ::: | ::: | ::: | ::: | | ||
+ | ^Video input |None|MIPI camera interface (CSI)|| | ||
+ | ^Video outputs | ||
+ | ^Audio inputs | ||
+ | ^Audio outputs | ||
+ | ^On-board storage | ||
+ | ^On-board network | ||
+ | ^ ::: | ::: | ::: |Bluetooth 4.1 BLE| | ||
+ | ^ ::: | ::: | ::: | | | ||
+ | ^Low-level peripherals | ||
+ | ^ ::: | ::: | ::: | ::: | | ||
+ | ^ ::: | ::: | ::: | ::: | | ||
+ | ^ ::: | ::: | ::: | ::: | | ||
+ | ^Power ratings | ||
+ | ^Power source | ||
+ | ^Size |65 mm × 30 mm × 5 mm (2.56 in × 1.18 in × 0.20 in)||| | ||
+ | ^Weight | ||
+ | ^Console | ||
+ | ^Generation | ||
+ | ^Obsolescence | ||
+ | ^ | ::: | ::: | ::: | | ||
+ | ^Statement | ||
+ | ^Type ^ **Zero** | ||
+ | |||
+ | </ | ||
+ | === Raspberry Pi Boards === | ||
+ | As for today, on the market there are available few models of Raspberry Pi boards, from tiny ones to more powerful. User can choose the right board to fit the price and functionality to his project development needs. Below figures are listed form the tiny/cheap to most sophisticated Raspberry Pi models. | ||
+ | <figure label> | ||
+ | {{ : | ||
+ | < | ||
+ | </ | ||
+ | <figure label> | ||
+ | {{ : | ||
+ | < | ||
+ | </ | ||
+ | <figure label> | ||
+ | {{ : | ||
+ | < | ||
+ | </ | ||
+ | <figure label> | ||
+ | {{ : | ||
+ | < | ||
+ | </ | ||
+ | <figure label> | ||
+ | {{ : | ||
+ | < | ||
+ | </ | ||
+ | <figure label> | ||
+ | {{ : | ||
+ | < | ||
+ | </ | ||
+ | |||
+ | === General-Purpose Input-Output (GPIO) Connector === | ||
+ | Each Raspberry Pi model is equipped with standard 34/40-pis male connector containing universal GPIO ports, VCC 3.3/5V, GND, CLK, I2C/SPI buses pins which developers can use to connect their external sensors, switches and other controlled devices to the Raspberry Pi board and then program their behaviour within the code loaded to the board. | ||
+ | * Raspberry Pi 1 Models A+ and B+, Pi 2 Model B, Pi 3 Model B and Pi Zero (and Zero W) GPIO J8 have a 40-pin pinout. Raspberry Pi 1 Models A and B have only the first 26 pins. | ||
+ | <figure label> | ||
+ | {{ : | ||
+ | < | ||
+ | </ | ||
+ | * Model B rev. 2 also has a pad (called P5 on the board and P6 on the schematics) of 8 pins offering access to an additional 4 GPIO connections. | ||
+ | <figure label> | ||
+ | {{ : | ||
+ | < | ||
+ | </ | ||
+ | |||
+ | == HDMI Port == | ||
+ | Each Raspberry Pi model is equipped with the standard mini HDMI port allows user connect the monitor or TV set with the board.The electronic schematic is shown on the picture. | ||
+ | <figure label> | ||
+ | {{ : | ||
+ | < | ||
+ | </ | ||
+ | |||
+ | === Camera Port CSI === | ||
+ | Raspberry Pi boars Zero, 1, A+, 2, 3 are equipped with Camera interface (CSI) port allowing user connect the CCD camera following the MIPI standard. | ||
+ | <figure label> | ||
+ | {{ : | ||
+ | < | ||
+ | </ | ||
+ | <figure label> | ||
+ | {{ : | ||
+ | < | ||
+ | </ | ||
+ | |||
+ | === Display Port (DSI) === | ||
+ | Raspberry Pi boars 2, 3 are equipped with LCD Display interface(DSI) port allowing the user to connect the LCD touch display to the board. | ||
+ | The official Raspberry Pi LCD touch display shown in the figure below is 800 x 480 dpi 7" size can be connected to the Raspberry board using the DSI interface. Such an assembly can be used in the projects to display controlling application view and with the ability to handle fingers touchscreen controls the project behaviour. The LCD can be mounted in portrait/ | ||
+ | <figure label> | ||
+ | {{ : | ||
+ | < | ||
+ | </ | ||
+ | |||
+ | <figure label> | ||
+ | {{ : | ||
+ | < | ||
+ | </ | ||
+ | |||
+ | ===USB and LAN Ports=== | ||
+ | Raspberry PI models boars Zero, 1, A+, 2, 3 contains USB ports (from 1 up to 4) and models boars 1, A+, 2, 3 the LAN port for TCP/IP network connections. This ports can be used for mouse/ | ||
+ | <figure label> | ||
+ | {{ : | ||
+ | < | ||
+ | </ | ||
+ | ==== ==== | ||
+ | <box # | ||
+ | <box # | ||
+ | ==== Raspberry Pi Sensors ==== | ||
+ | <box # | ||
+ | <box # | ||
+ | |||
+ | Raspberry Pi boards offer an easy way to connect different sensors and control devices. With specially designed I/O pins available to program them by developers the amount of possible implementations growth year by year. Any I/O General Purpose Input-Output Ports (GPIO) can be set as Digital Input or Output. The board contains two PWM pins which can be used as output analogue signals. Some of the interface libraries, such as pigpio or wiringPi, support this feature. It is also the way the Raspberry Pi outputs analogue audio. | ||
+ | |||
+ | === Touch Sensors === | ||
+ | == Button == | ||
+ | |||
+ | A **pushbutton** is an electromechanical sensor that connects or disconnects two points in a circuit when the force is applied. Button output discrete value is either //HIGH// or // | ||
+ | |||
+ | A **microswitch**, | ||
+ | |||
+ | The most common use of a push button is as an input device. Both force solutions can be used as simple object detectors, or as end switches in the industrial devices. | ||
+ | |||
+ | <figure label> | ||
+ | {{ : | ||
+ | < | ||
+ | </ | ||
+ | <figure label> | ||
+ | {{ : | ||
+ | < | ||
+ | </ | ||
+ | |||
+ | To proper work with the button, the GPIO4 must be configured as an digital input. Pressing the push button connects the GPIO4 pin to the boards GND. On Raspberry Pi GPIO input pins are normally pulled up to 3.3 V. When the button is pressed, and GPIO4 is read using GPIO.input, it will return the //FALSE// result. Each GPIO pin can be configured to use internal pull-up or pull-down resistors. Using a GPIO pin as an input, these resistors can be configured using the optional // | ||
+ | |||
+ | An example code: | ||
+ | <code Python> | ||
+ | #Python code for Raspberry Pi | ||
+ | |||
+ | import RPi.GPIO as GPIO | ||
+ | import time | ||
+ | |||
+ | GPIO.setmode(GPIO.BCM) | ||
+ | s_pin = 7 #Select the GPIO4 pin | ||
+ | |||
+ | #Set the GPIO4 port to input mode | ||
+ | GPIO.setup(s_pin, | ||
+ | |||
+ | while True: | ||
+ | input_state = GPIO.input(s_pin) | ||
+ | if input_state == False: | ||
+ | print(' | ||
+ | time.sleep(0.2) | ||
+ | |||
+ | </ | ||
+ | |||
+ | Running the code as superuser shows: | ||
+ | < | ||
+ | pi@raspberrypi ~ $ sudo python switch.py | ||
+ | Button Pressed | ||
+ | Button Pressed | ||
+ | Button Pressed | ||
+ | Button Pressed | ||
+ | </ | ||
+ | |||
+ | ==Force Sensor== | ||
+ | A force sensor predictably changes resistance, depending on the applied force to its surface. Force-sensing resistors are manufactured in different shapes and sizes, and they can measure not only direct force but also the tension, compression, | ||
+ | |||
+ | Force sensors are used as control buttons or to determine weight. | ||
+ | |||
+ | <figure label> | ||
+ | {{ : | ||
+ | < | ||
+ | </ | ||
+ | |||
+ | <figure label> | ||
+ | {{ : | ||
+ | < | ||
+ | </ | ||
+ | |||
+ | An example code: | ||
+ | <code Python> | ||
+ | #Python code for Raspberry Pi | ||
+ | |||
+ | import RPi.GPIO as GPIO | ||
+ | import time | ||
+ | |||
+ | GPIO.setmode(GPIO.BCM) | ||
+ | |||
+ | a_pin = 7 # | ||
+ | b_pin = 29 #Select the GPIO5 pin | ||
+ | |||
+ | def discharge(): | ||
+ | GPIO.setup(a_pin, | ||
+ | GPIO.setup(b_pin, | ||
+ | GPIO.output(b_pin, | ||
+ | time.sleep(0.005) | ||
+ | |||
+ | def charge_time(): | ||
+ | GPIO.setup(b_pin, | ||
+ | GPIO.setup(a_pin, | ||
+ | count = 0 | ||
+ | GPIO.output(a_pin, | ||
+ | while not GPIO.input(b_pin): | ||
+ | count = count + 1 | ||
+ | return count | ||
+ | |||
+ | def analog_read(): | ||
+ | discharge() | ||
+ | return charge_time() | ||
+ | |||
+ | while True: | ||
+ | print(analog_read()) | ||
+ | time.sleep(1) | ||
+ | </ | ||
+ | |||
+ | Running the code as superuser shows: | ||
+ | < | ||
+ | $ sudo python pot_step.py | ||
+ | 10 | ||
+ | 12 | ||
+ | 10 | ||
+ | 10 | ||
+ | 16 | ||
+ | 23 | ||
+ | 43 | ||
+ | 53 | ||
+ | 67 | ||
+ | 72 | ||
+ | 86 | ||
+ | 105 | ||
+ | 123 | ||
+ | 143 | ||
+ | 170 | ||
+ | </ | ||
+ | The idea of how to read the force sensor changing value is called **step response**. It works by checking how the circuit responds to the step change when an output is switched from low to high. | ||
+ | Raspberry Pi isn't equipped with an ADC converter. So it is impossible to read voltage directly. However, it can be measured how long the capacitor will fill with the charge to the extent that it gets voltage above 1.65 V or so that constitutes a high digital input. The speed at which the capacitor fills with charge depends on the value of the variable resistor (Rt). The lower the resistance, the faster the capacitor fills with charge, and the voltage rises. To get the proper value, the circuit must empty the capacitor each time before the reading starts. In the schematic the GPIO4 is used to charge the capacitor and GPIO5 is used to discharge the capacitor through the 10 kΩ resistor. Both resistors are used to make sure that there is no way too much current can flow as the capacitor is charged and discharged. To discharge it, connection GPIO4 is set to be an input, effectively disconnecting Rc and Rt from the circuit. Connection GPIO5 is then set to be an output and low. It is held there for 5 milliseconds, | ||
+ | |||
+ | ==Capacitive Sensor== | ||
+ | Capacitive sensors are a range of sensors that use capacitance to measure changes in the surrounding environment. A capacitive sensor consists of a capacitor that is charged with a certain amount of current until the threshold voltage. A human finger, liquids or other conductive or dielectric materials that touch the sensor, can influence a charge time and a voltage level in the sensor. Measuring charge time and a voltage level gives information about changes in the environment. | ||
+ | |||
+ | Capacitive sensors are used as input devices and can measure proximity, humidity, fluid level and other physical parameters or serve as an input for electronic device control. | ||
+ | |||
+ | <figure label> | ||
+ | {{ : | ||
+ | < | ||
+ | </ | ||
+ | |||
+ | <figure label> | ||
+ | {{ : | ||
+ | < | ||
+ | </ | ||
+ | |||
+ | <code Python> | ||
+ | #Python code for Raspberry Pi | ||
+ | |||
+ | import time | ||
+ | import pigpio # | ||
+ | RXD=15 | ||
+ | |||
+ | pi = pigpio.pi() | ||
+ | if not pi.connected: | ||
+ | | ||
+ | |||
+ | pigpio.exceptions = False #Ignore error if already set as bit bang read. | ||
+ | pi.bb_serial_read_open(RXD, | ||
+ | pigpio.exceptions = True | ||
+ | pi.bb_serial_invert(RXD, | ||
+ | stop = time.time() + 60.0 | ||
+ | while time.time() < stop: | ||
+ | (count, data) = pi.bb_serial_read(RXD) | ||
+ | if count: | ||
+ | print(data) | ||
+ | time.sleep(0.2) | ||
+ | |||
+ | pi.bb_serial_read_close(RXD) | ||
+ | |||
+ | pi.stop() | ||
+ | </ | ||
+ | |||
+ | === Proximity and Distance Sensors === | ||
+ | ==Ultrasound Sensor== | ||
+ | Ultrasound (ultrasonic) sensor measures the distance to objects by emitting ultrasound and measuring its returning time. The sensor consists of an ultrasonic emitter and receiver; sometimes, they are combined in a single device for emitting and receiving. Ultrasonic sensors can measure greater distances and cost less than infrared sensors, but are more imprecise and interfere which each other measurement if more than one is used. Simple sensors have trigger pin and echo pin, when the trigger pin is set high for the small amount of time ultrasound is emitted and on echo pin, response time is measured. Ultrasonic sensors are used in car parking sensors and robots for proximity detection. | ||
+ | |||
+ | <figure label> | ||
+ | {{ : | ||
+ | < | ||
+ | </ | ||
+ | |||
+ | Examples of IoT applications are robotic obstacle detection and room layout scanning. | ||
+ | |||
+ | <figure label> | ||
+ | {{ : | ||
+ | < | ||
+ | </ | ||
+ | |||
+ | An example code: | ||
+ | <code Python> | ||
+ | #Python code for Raspberry Pi | ||
+ | |||
+ | import RPi.GPIO as GPIO | ||
+ | import time | ||
+ | |||
+ | TRIG = 7 #Define a trigger pin GPIO4 | ||
+ | ECHO = 29 #Define an echo pin GPIO5 | ||
+ | |||
+ | print (" | ||
+ | |||
+ | GPIO.setup(TRIG, | ||
+ | GPIO.setup(ECHO, | ||
+ | |||
+ | GPIO.output (TRIG, | ||
+ | |||
+ | print (" | ||
+ | time.sleep(2) | ||
+ | |||
+ | GPIO.output (TRIG, True) | ||
+ | time.sleep (0.00001) | ||
+ | GPIO.output (TRIG, False) | ||
+ | |||
+ | while GPIO.input(ECHO) == 0: | ||
+ | pulse_start = time.time() | ||
+ | | ||
+ | while GPIO.input(ECHO) == 1: | ||
+ | pulse_end = time.time() | ||
+ | | ||
+ | pulse_duration = pulse_end - pulse_start | ||
+ | distance = pulse_duration*17150 | ||
+ | distance = round(distance, | ||
+ | print (" | ||
+ | </ | ||
+ | |||
+ | Running the code as superuser shows: | ||
+ | < | ||
+ | pi@raspberrypi > $ sudo python range_sensor.py | ||
+ | Distance Measurement To Settle | ||
+ | Distance: 23.54 cm | ||
+ | pi@raspberrypi > $ | ||
+ | </ | ||
+ | |||
+ | ==Motion Detector== | ||
+ | The motion detector is a sensor that detects moving objects, most people. Motion detectors use different technologies, | ||
+ | |||
+ | Motion sensors are used for security purposes, automated light and door systems. As an example in IoT, the PIR motion sensor can be used to detect motion in security systems a house or any building. | ||
+ | |||
+ | <figure label> | ||
+ | {{ : | ||
+ | < | ||
+ | </ | ||
+ | |||
+ | <figure label> | ||
+ | {{ : | ||
+ | < | ||
+ | </ | ||
+ | |||
+ | An example code: | ||
+ | <code Python> | ||
+ | #Python code for Raspberry Pi | ||
+ | |||
+ | pirPin = 7; //Passive Infrared (PIR) sensor output is connected to the GPIO4 pin | ||
+ | |||
+ | GPIO.setup(pirPin , | ||
+ | |||
+ | while 1: | ||
+ | #Read the digital value of the PIR motion sensor GPIO4 | ||
+ | pirReading = GPIO.input(pirPin) | ||
+ | print (piReading) | ||
+ | |||
+ | if pirReading == True: #Motion was detected | ||
+ | print (' | ||
+ | time.sleep(10) | ||
+ | </ | ||
+ | |||
+ | ==Gyroscope== | ||
+ | A gyroscope is a sensor that measures the angular velocity. The sensor is made of the microelectromechanical system (MEMS) technology and is integrated into the chip. The output of the sensor can be either analogue or digital value of information, | ||
+ | Gyroscope sensors are used in aviation, navigation and motion control. | ||
+ | |||
+ | Gyroscope sensors are used in aviation, navigation and motion control. | ||
+ | |||
+ | <figure label> | ||
+ | {{ : | ||
+ | < | ||
+ | </ | ||
+ | |||
+ | <figure label> | ||
+ | {{ : | ||
+ | < | ||
+ | </ | ||
+ | |||
+ | The example code for the FXAS21002C sensor used in the breakout board: | ||
+ | <code Python> | ||
+ | #Python code for Raspberry Pi | ||
+ | # | ||
+ | |||
+ | from __future__ import division, print_function | ||
+ | from nxp_imu import IMU | ||
+ | import time | ||
+ | |||
+ | imu = IMU(gs=4, dps=2000, verbose=True) | ||
+ | header = 67 | ||
+ | print(' | ||
+ | print(" | ||
+ | print(' | ||
+ | for _ in range(10): | ||
+ | a, m, g = imu.get() | ||
+ | print(' | ||
+ | | ||
+ | a[0], a[1], a[2], | ||
+ | m[0], m[1], m[2], | ||
+ | g[0], g[1], g[2]) | ||
+ | ) | ||
+ | time.sleep(0.50) | ||
+ | print(' | ||
+ | print(' | ||
+ | print(' | ||
+ | print(' | ||
+ | print('' | ||
+ | </ | ||
+ | |||
+ | ==Compass== | ||
+ | A compass is a sensor, that can measure the orientation of the device to the magnetic field of the Earth. Solid state compass consists of the magnetometer and accelerometers in a single chip to precisely calculate the position of the device. Devices communicate through I2C or SPI interfaces and can return calculated heading, pitch and roll and raw accelerometer and magnetometer values. Compass is used in outdoor navigation for mobile devices, robots, quadcopters. | ||
+ | |||
+ | <figure label> | ||
+ | {{ : | ||
+ | < | ||
+ | </ | ||
+ | |||
+ | <figure label> | ||
+ | {{ : | ||
+ | < | ||
+ | </ | ||
+ | |||
+ | The example code: | ||
+ | < | ||
+ | 1. Install i2c: | ||
+ | sudo apt-get install i2c-tools | ||
+ | 2. edit file / | ||
+ | and comment out the line blacklist i2c-bcm2708 | ||
+ | 3. edit / | ||
+ | | ||
+ | | ||
+ | 4. Allow i2c access from users other than root, | ||
+ | by creating the file / | ||
+ | | ||
+ | 5. Reboot the Pi. When it goes up again, type: | ||
+ | ls /dev/i2c* | ||
+ | On Pi (Model B, Revision 2 version, early 2013) it generates: | ||
+ | /dev/i2c-0 /dev/i2c-1 | ||
+ | Optional: For python, install the smbus python library with: | ||
+ | 1. apt-get install python-smbus | ||
+ | 2. Install Python 3, can’t hurt, and i2clibraries needs it. | ||
+ | Just type sudo apt-get install python3 | ||
+ | 3. Test if the compass is detected, by typing: | ||
+ | | ||
+ | 4. Replace with 0 for Revision 1 Raspberry Pis and with | ||
+ | 1 for Revision 2 boards. This is the output: | ||
+ | 0 1 2 3 4 5 6 7 8 9 a b c d e f | ||
+ | 00: -- -- -- -- -- -- -- -- -- -- -- -- -- | ||
+ | 10: -- -- -- -- -- -- -- -- -- -- -- -- -- -- 1e -- | ||
+ | 20: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- | ||
+ | 30: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- | ||
+ | 40: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- | ||
+ | 50: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- | ||
+ | 60: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- | ||
+ | 70: -- -- -- -- -- -- -- -- | ||
+ | |||
+ | Tip: if you don’t see it, it’s because you haven’t welded the pins to the sensor. Just press with your finger. Or weld it. | ||
+ | 1. Add the quick2wire code. Pull from git: | ||
+ | git clone https:// | ||
+ | On / | ||
+ | 2. export PYTHONPATH=$PYTHONPATH: | ||
+ | Add i2clibraries. Pull from git: | ||
+ | clone https:// | ||
+ | </ | ||
+ | |||
+ | === Environment Sensors === | ||
+ | ==Temperature Sensor== | ||
+ | A temperature sensor is a device that is used to determine the temperature of the surrounding environment. Most temperature sensors work on the principle that the resistance of the material is changed depending on its temperature. The most common temperature sensors are: | ||
+ | * **thermocouple** – consists of two junctions of dissimilar metals, | ||
+ | * **thermistor** – includes the temperature-dependent ceramic resistor, | ||
+ | * **resistive temperature detector** – is made of a pure metal coil. | ||
+ | The main difference between sensors is the measured temperature range, precision and response time. Temperature sensor usually outputs the analogue value, but some existing sensors have a digital interface ((http:// | ||
+ | |||
+ | The temperature sensors most commonly are used in environmental monitoring devices and thermoelectric switches. In IoT applications, | ||
+ | |||
+ | <figure label> | ||
+ | {{ : | ||
+ | < | ||
+ | </ | ||
+ | |||
+ | <figure label> | ||
+ | {{ : | ||
+ | < | ||
+ | </ | ||
+ | |||
+ | An example code is similar to the Raspberry Pi force sensor sample. The thermistor changes its resistance depends on the environment temperature, | ||
+ | <code Python> | ||
+ | #Python code for Raspberry Pi | ||
+ | |||
+ | import RPi.GPIO as GPIO | ||
+ | import time | ||
+ | |||
+ | GPIO.setmode(GPIO.BCM) | ||
+ | |||
+ | a_pin = 7 # | ||
+ | b_pin = 29 #Select the GPIO5 pin | ||
+ | |||
+ | def discharge(): | ||
+ | GPIO.setup(a_pin, | ||
+ | GPIO.setup(b_pin, | ||
+ | GPIO.output(b_pin, | ||
+ | time.sleep(0.005) | ||
+ | |||
+ | def charge_time(): | ||
+ | GPIO.setup(b_pin, | ||
+ | GPIO.setup(a_pin, | ||
+ | count = 0 | ||
+ | GPIO.output(a_pin, | ||
+ | while not GPIO.input(b_pin): | ||
+ | count = count + 1 | ||
+ | return count | ||
+ | |||
+ | def analog_read(): | ||
+ | discharge() | ||
+ | return charge_time() | ||
+ | |||
+ | while True: | ||
+ | print(analog_read()) | ||
+ | time.sleep(1) | ||
+ | </ | ||
+ | |||
+ | ==Humidity Sensor== | ||
+ | A humidity sensor (hygrometer) is a sensor that detects the amount of water or water vapour in the environment. The most common principle of the air humidity sensors is the change of capacitance or resistance of materials that absorb the moisture from the environment. Soil humidity sensors measure the resistance between the two electrodes. The resistance between electrodes is influenced by soluble salts and water amount in the soil. The output of a humidity sensor is usually an analogue signal value ((https:// | ||
+ | |||
+ | Example IoT applications are monitoring of humidor, greenhouse temperature and humidity, agricultural environment and art gallery and museum environment. | ||
+ | |||
+ | <figure label> | ||
+ | {{ : | ||
+ | < | ||
+ | </ | ||
+ | |||
+ | <figure label> | ||
+ | {{ : | ||
+ | < | ||
+ | </ | ||
+ | |||
+ | An example code ((http:// | ||
+ | < | ||
+ | 1. Enter this at the command prompt to download the library: | ||
+ | git clone https:// | ||
+ | |||
+ | 2. Change directories with: | ||
+ | cd Adafruit_Python_DHT | ||
+ | |||
+ | 3. Now enter this: | ||
+ | sudo apt-get install build-essential python-dev | ||
+ | |||
+ | 4. Then install the library with: | ||
+ | sudo python setup.py install | ||
+ | </ | ||
+ | |||
+ | <code Python> | ||
+ | #Python code for Raspberry Pi | ||
+ | # | ||
+ | |||
+ | import sys | ||
+ | import Adafruit_DHT | ||
+ | |||
+ | while True: | ||
+ | humidity, temperature = Adafruit_DHT.read_retry(11, | ||
+ | print (' | ||
+ | |||
+ | </ | ||
+ | |||
+ | ==Sound Sensor== | ||
+ | A sound sensor is a sensor that detects vibrations in a gas, liquid or solid environments. At first, the sound wave pressure makes mechanical vibrations, who transfers to changes in capacitance, | ||
+ | |||
+ | Sound sensors are used in drone detection, gunshot alert, seismic detection and vault safety alarm. | ||
+ | |||
+ | <figure label> | ||
+ | {{ : | ||
+ | < | ||
+ | </ | ||
+ | |||
+ | <figure label> | ||
+ | {{ : | ||
+ | < | ||
+ | </ | ||
+ | |||
+ | An example code: | ||
+ | <code Python> | ||
+ | #Python code for Raspberry Pi | ||
+ | |||
+ | import time | ||
+ | import RPi.GPIO as GPIO | ||
+ | from qhue import Bridge | ||
+ | |||
+ | GPIO.setmode(GPIO.BCM) #Use board pin numbers | ||
+ | pin = 7 #Define GPIO4 as Input | ||
+ | GPIO.setup(pin, | ||
+ | |||
+ | def callback (pin) | ||
+ | if GPIO.input (pin) | ||
+ | print (" | ||
+ | else: | ||
+ | print (" | ||
+ | #Activate when pin changed its state | ||
+ | GPIO.add_event_detect(pin, | ||
+ | #Assign function to GPIO PIN run it on changes | ||
+ | GPIO.add_event_callback(pin, | ||
+ | | ||
+ | #Infinite loop | ||
+ | while True: | ||
+ | | ||
+ | </ | ||
+ | |||
+ | ==Chemical/ | ||
+ | Gas sensors are a sensor group, that can detect and measure a concentration of certain gasses in the air. The working principle of electrochemical sensors is to absorb the gas and to create current from an electrochemical reaction. For process acceleration, | ||
+ | |||
+ | Gas sensors are used for safety devices, to control air quality and for manufacturing equipment. Examples of IoT applications are air quality control management in smart buildings and smart cities or toxic gas detection in sewers and underground mines. | ||
+ | |||
+ | <figure label> | ||
+ | {{ : | ||
+ | < | ||
+ | </ | ||
+ | |||
+ | <figure label> | ||
+ | {{ : | ||
+ | < | ||
+ | </ | ||
+ | |||
+ | An example code: | ||
+ | < | ||
+ | #Python code for Raspberry Pi | ||
+ | |||
+ | 1. git clone https:// | ||
+ | 2. cd Raspberry-Pi-Gas-Sensor-MQ | ||
+ | 3. sudo python example.py | ||
+ | </ | ||
+ | |||
+ | <code Python> | ||
+ | #Python code for Raspberry Pi | ||
+ | # | ||
+ | |||
+ | import PCF8591 as ADC | ||
+ | import RPi.GPIO as GPIO | ||
+ | import time | ||
+ | import math | ||
+ | |||
+ | DO = 17 | ||
+ | Buzz = 18 | ||
+ | GPIO.setmode(GPIO.BCM) | ||
+ | |||
+ | def setup(): | ||
+ | ADC.setup(0x48) | ||
+ | GPIO.setup | ||
+ | GPIO.setup | ||
+ | GPIO.output (Buzz, 1) | ||
+ | |||
+ | def Print(x): | ||
+ | if x == 1: | ||
+ | print ('' | ||
+ | print (' | ||
+ | print (' | ||
+ | print (' | ||
+ | print ('' | ||
+ | if x == 0: | ||
+ | print ('' | ||
+ | print (' | ||
+ | print (' | ||
+ | print (' | ||
+ | print ('' | ||
+ | |||
+ | def loop(): | ||
+ | status = 1 | ||
+ | count = 0 | ||
+ | while True: | ||
+ | print (ADC.read(0)) | ||
+ | |||
+ | tmp = GPIO.input(DO); | ||
+ | if tmp != status: | ||
+ | print(tmp) | ||
+ | status = tmp | ||
+ | if status == 0: | ||
+ | count += 1 | ||
+ | if count % 2 == 0: | ||
+ | GPIO.output(Buzz, | ||
+ | else: | ||
+ | GPIO.output(Buzz, | ||
+ | else: | ||
+ | GPIO.output(Buzz, | ||
+ | count = 0 | ||
+ | |||
+ | time.sleep(0.2) | ||
+ | |||
+ | def destroy(): | ||
+ | GPIO.output(Buzz, | ||
+ | GPIO.cleanup() | ||
+ | |||
+ | if __name__ == ' | ||
+ | try: | ||
+ | setup() | ||
+ | loop() | ||
+ | except KeyboardInterrupt: | ||
+ | destroy() | ||
+ | </ | ||
+ | |||
+ | === Other Sensors === | ||
+ | ==Global Positioning System== | ||
+ | A GPS receiver is a device, that can receive information from a global navigation satellite system and calculate its position on the Earth. | ||
+ | |||
+ | A GPS receiver is used for device location tracking. Real world applications might be pet, kid or personal belonging location tracking. | ||
+ | |||
+ | <figure label> | ||
+ | {{ : | ||
+ | < | ||
+ | </ | ||
+ | |||
+ | <figure label> | ||
+ | {{ : | ||
+ | < | ||
+ | </ | ||
+ | |||
+ | The example code: | ||
+ | <code Python> | ||
+ | #Python code for Raspberry Pi | ||
+ | # | ||
+ | |||
+ | import os | ||
+ | import pygame, sys | ||
+ | from pygame.locals import * | ||
+ | import serial | ||
+ | |||
+ | #Initialise serial port on /ttyUSB0 | ||
+ | ser = serial.Serial('/ | ||
+ | #Set font size MAX 100 | ||
+ | fontsize = 50 | ||
+ | |||
+ | #Calculate window size | ||
+ | width = fontsize * 17 | ||
+ | height = fontsize + 10 | ||
+ | |||
+ | #Initilaise pygame | ||
+ | pygame.init() | ||
+ | windowSurfaceObj = pygame.display.set_mode((width, | ||
+ | fontObj = pygame.font.Font(' | ||
+ | pygame.display.set_caption(' | ||
+ | redColor = pygame.Color(255, | ||
+ | greenColor = pygame.Color(0, | ||
+ | yellowColor = pygame.Color(255, | ||
+ | blackColor = pygame.Color(0, | ||
+ | |||
+ | fix = 1 | ||
+ | color = redColor | ||
+ | x = 0 | ||
+ | while x == 0: | ||
+ | gps = ser.readline() | ||
+ | #Print (all NMEA strings) | ||
+ | print (gps) | ||
+ | #Check gps fix status | ||
+ | if gps[1:6] == " | ||
+ | fix = int(gps[9: | ||
+ | if fix == 2: | ||
+ | color = yellowColor | ||
+ | if fix == 3: | ||
+ | color = greenColor | ||
+ | # | ||
+ | if gps[1 : 6] == " | ||
+ | #Clear window | ||
+ | pygame.draw.rect(windowSurfaceObj, | ||
+ | pygame.display.update(pygame.Rect(0, | ||
+ | #Get time | ||
+ | time = gps[7:9] + ":" | ||
+ | #If 2 or 3D fix get lat and long | ||
+ | if fix > 1: | ||
+ | lat = " " + gps[18:20] + " | ||
+ | lon = " " + gps[30:33] + " | ||
+ | #If no fix | ||
+ | else: | ||
+ | lat = " No Valid Data " | ||
+ | lon = " " | ||
+ | #Print new values | ||
+ | msgSurfaceObj = fontObj.render(str(time), | ||
+ | msgRectobj = msgSurfaceObj.get_rect() | ||
+ | msgRectobj.topleft =(2,0) | ||
+ | windowSurfaceObj.blit(msgSurfaceObj, | ||
+ | |||
+ | msgSurfaceObj = fontObj.render(str(lat), | ||
+ | msgRectobj = msgSurfaceObj.get_rect() | ||
+ | msgRectobj.topleft =(210,0) | ||
+ | windowSurfaceObj.blit(msgSurfaceObj, | ||
+ | |||
+ | msgSurfaceObj = fontObj.render(str(lon), | ||
+ | msgRectobj = msgSurfaceObj.get_rect() | ||
+ | msgRectobj.topleft =(495,0) | ||
+ | windowSurfaceObj.blit(msgSurfaceObj, | ||
+ | pygame.display.update(pygame.Rect(0, | ||
+ | fix = 1 | ||
+ | color = redColor | ||
+ | |||
+ | # | ||
+ | for event in pygame.event.get(): | ||
+ | if event.type == QUIT or (event.type == KEYDOWN and event.key == K_ESCAPE): | ||
+ | | ||
+ | | ||
+ | } | ||
+ | </ | ||
+ | ==== ==== | ||
+ | <box # | ||
+ | <box # | ||
+ | ==== Raspberry Pi Drivers and Driving ==== | ||
+ | <box # | ||
+ | <box # | ||
+ | |||
+ | |||
+ | === Optical Device Drivers and Their Devices ==== | ||
+ | |||
+ | == Light-Emitting Diode == | ||
+ | The light-emitting diode also called LED is a special type of diodes which emits light, unlike the other diodes. LED has a completely different body which is made of transparent plastic that protects the diode and lets it emit light. Like the other diodes LED conducts the current in only one way, so it is essential to connect it to the scheme correctly. There are two safe ways how to determine the direction of the diode: | ||
+ | * in the cathodes side of the diode its side is chipped, | ||
+ | * anodes leg usually is longer than the cathodes leg. | ||
+ | |||
+ | <figure label> | ||
+ | {{ : | ||
+ | < | ||
+ | </ | ||
+ | |||
+ | The LED is one of the best light sources. Unlike incandescent light bulb LED transforms most of the power into light, not warmth; it is more durable, works for a more extended period and can be manufactured in a smaller size. | ||
+ | |||
+ | The LED colour is determined by the semiconductors material. Diodes are usually made from silicon then LEDs are made from elements like gallium phosphate, silicon carbide and others. Because the semiconductors used are different, the voltage needed for the LED to shine is also different. In the table, you can see with which semiconductor you can get a specific colour and the voltage required to turn on the LED. | ||
+ | |||
+ | When LED is connected to the voltage and turned on a huge current starts to flow through it, and it can damage the diode. That is why all **LEDs have to be connected to current limiting resistor**. | ||
+ | |||
+ | Current limiting resistors resistance is determined by three parameters: | ||
+ | * //I_D// – current that can flow through the LED, | ||
+ | * //U_D// – Voltage that is needed to turn on the LED, | ||
+ | * //U// – combined voltage for LED and resistor. | ||
+ | |||
+ | To calculate the resistance needed for a diode, this is what you have to do. | ||
+ | - Find out the voltage needed for the diode to work UD; you can find it in the diodes parameters table. | ||
+ | - Find out the amperage needed for the LED to shine ID; it can be found in the LEDs datasheet, but if you can’t find it then 20 mA current is usually a correct and safe choice. | ||
+ | - Find out the combined voltage for the LED and resistor; usually, it is the feeding voltage for the scheme. | ||
+ | - Insert all the values into this equation: //R = (U – U_D) / I_D// | ||
+ | - You get the resistance for the resistor for the safe use of the LED. | ||
+ | - Find resistors nominal that is the same or bigger than the calculated resistance. | ||
+ | |||
+ | <figure label> | ||
+ | {{ : | ||
+ | < | ||
+ | </ | ||
+ | |||
+ | The example of the blinking LED code: | ||
+ | <code Python> | ||
+ | #Raspberry Pi Python sample code | ||
+ | |||
+ | import RPi.GPIO as GPIO | ||
+ | import time | ||
+ | |||
+ | LED = 18 #GPIO04 port | ||
+ | |||
+ | GPIO.setmode(GPIO.BCM) | ||
+ | GPIO.setwarnings(False) | ||
+ | GPIO.setup(LED, | ||
+ | print ("LED on") | ||
+ | GPIO.output(LED, | ||
+ | time.sleep(1) | ||
+ | print ("LED off") | ||
+ | GPIO.output(LED, | ||
+ | </ | ||
+ | |||
+ | === Displays === | ||
+ | Using //display// is a quick way to get a feedback information from the device. There are many display technologies compatible with Arduino. For IoT solutions low power, easy to use and monochrome displays are used: | ||
+ | * // | ||
+ | * //Organic light-emitting diode display// (OLED), | ||
+ | * // | ||
+ | |||
+ | ==Liquid-Crystal Display (LCD)== | ||
+ | LCD uses modulating properties of liquid crystal light to block the incoming light. Thus when a voltage is applied to a pixel, it has a dark colour. A display consists of layers of electrodes, polarising filters, liquid crystals and reflector or back-light. Liquid crystals do not emit the light directly; they do it through reflection or backlight. Because of this reason, they are more energy efficient. Small, monochrome LCDs are widely used in devices to show a little numerical or textual information like temperature, | ||
+ | |||
+ | <figure label> | ||
+ | {{ : | ||
+ | < | ||
+ | </ | ||
+ | |||
+ | <figure label> | ||
+ | {{ : | ||
+ | < | ||
+ | </ | ||
+ | |||
+ | The example code: | ||
+ | <code Python> | ||
+ | #Raspberry Pi Python sample code | ||
+ | # | ||
+ | #Example using a character LCD connected to a Raspberry Pi | ||
+ | |||
+ | import time | ||
+ | import Adafruit_CharLCD as LCD | ||
+ | |||
+ | #Raspberry Pi pin setup | ||
+ | lcd_rs = 25 | ||
+ | lcd_en = 24 | ||
+ | lcd_d4 = 23 | ||
+ | lcd_d5 = 17 | ||
+ | lcd_d6 = 18 | ||
+ | lcd_d7 = 22 | ||
+ | lcd_backlight = 2 | ||
+ | |||
+ | #Define LCD column and row size for 16x2 LCD. | ||
+ | lcd_columns = 16 | ||
+ | lcd_rows = 2 | ||
+ | |||
+ | lcd = LCD.Adafruit_CharLCD(lcd_rs, | ||
+ | | ||
+ | |||
+ | lcd.message(' | ||
+ | #Wait 5 seconds | ||
+ | |||
+ | time.sleep(5.0) | ||
+ | lcd.clear() | ||
+ | text = raw_input(" | ||
+ | lcd.message(text) | ||
+ | |||
+ | #Wait 5 seconds | ||
+ | time.sleep(5.0) | ||
+ | lcd.clear() | ||
+ | lcd.message(' | ||
+ | |||
+ | time.sleep(5.0) | ||
+ | lcd.clear() | ||
+ | </ | ||
+ | |||
+ | ==Organic Light-Emitting Diode Display (OLED)== | ||
+ | OLED display uses electroluminescent materials that emit light when the current passes through these materials. The display consists of two electrodes and a layer of an organic compound. OLED displays are thinner than LCDs, they have higher contrast, and they can be more energy efficient depending on usage. OLED displays are commonly used in mobile devices like smartwatches, | ||
+ | |||
+ | <figure label> | ||
+ | {{ : | ||
+ | < | ||
+ | </ | ||
+ | |||
+ | <figure label> | ||
+ | {{ : | ||
+ | < | ||
+ | </ | ||
+ | |||
+ | < | ||
+ | 1. git clone https:// | ||
+ | 2. cd Adafruit_Python_SSD1306 | ||
+ | For Python 2: | ||
+ | 3. sudo python setup.py install | ||
+ | For Python3: | ||
+ | 4. sudo python3 setup.py install | ||
+ | </ | ||
+ | < | ||
+ | cd examples | ||
+ | Choose one of existing examples: | ||
+ | - animate.py | ||
+ | - buttons.py | ||
+ | - image.py | ||
+ | - shapes.py | ||
+ | - stats.py | ||
+ | </ | ||
+ | |||
+ | ==Electronic Ink Display (E-ink)== | ||
+ | E-ink display uses charged particles to create a paper-like effect. The display consists of transparent microcapsules filled with oppositely charged white and black particles between electrodes. Charged particles change their location, depending on the orientation of the electric field, thus individual pixels can be either black or white. The image does not need the power to persist on the screen; power is used only when the image is changed. Thus e-ink display is very energy efficient. It has high contrast and viewing angle, but it has a low refresh rate. E-ink displays are commonly used in e-riders, smartwatches, | ||
+ | |||
+ | <figure label> | ||
+ | {{ : | ||
+ | < | ||
+ | </ | ||
+ | |||
+ | <figure label> | ||
+ | {{ : | ||
+ | < | ||
+ | </ | ||
+ | |||
+ | <code Python> | ||
+ | #Raspberry Pi Python sample code | ||
+ | #From https:// | ||
+ | |||
+ | import time, datetime, sys, signal, urllib, requests | ||
+ | from EPD_driver import EPD_driver | ||
+ | def handler(signum, | ||
+ | print (' | ||
+ | sys.exit(0) | ||
+ | signal.signal(signal.SIGTERM, | ||
+ | bus = 0 | ||
+ | device = 0 | ||
+ | disp = EPD_driver(spi = SPI.SpiDev(bus, | ||
+ | print ("disp size : %dx%d" | ||
+ | print (' | ||
+ | disp.Dis_Clear_full() | ||
+ | disp.delay() | ||
+ | #Display part | ||
+ | disp.EPD_init_Part() | ||
+ | disp.delay() | ||
+ | imagenames = [] | ||
+ | search = " | ||
+ | if search: | ||
+ | req = requests.get(search) | ||
+ | if req.status_code == 200: | ||
+ | for topic in req.json()[" | ||
+ | if " | ||
+ | for topic2 in topic[" | ||
+ | try: | ||
+ | url = topic2[" | ||
+ | text = topic2[" | ||
+ | if url: | ||
+ | imagenames.append( (url,text) ) | ||
+ | except: | ||
+ | #Print topic | ||
+ | pass | ||
+ | try: | ||
+ | url = topic[" | ||
+ | if url: | ||
+ | imagenames.append( url ) | ||
+ | except: | ||
+ | #Print topic | ||
+ | pass | ||
+ | else: | ||
+ | print (req.status_code) | ||
+ | #Font for drawing within PIL | ||
+ | myfont10 = ImageFont.truetype(" | ||
+ | myfont28 = ImageFont.truetype(" | ||
+ | #Mainimg is used as screen buffer, all image composing/ | ||
+ | #The mainimg is then copied to the display (drawing on the disp itself is no fun) | ||
+ | mainimg = Image.new(" | ||
+ | name = (" | ||
+ | skip = 0 | ||
+ | while 1: | ||
+ | for name2 in imagenames: | ||
+ | print (' | ||
+ | skip = (skip+1)%7 | ||
+ | try: | ||
+ | starttime = time.time() | ||
+ | if skip==0 and name2[0].startswith(" | ||
+ | name = name2 | ||
+ | urllib.urlretrieve(name[0], | ||
+ | name = (" | ||
+ | im = Image.open(name[0]) | ||
+ | print (name, im.format, im.size, im.mode) | ||
+ | im.thumbnail((296, | ||
+ | im = im.convert(" | ||
+ | #Print (' | ||
+ | loadtime = time.time() | ||
+ | print (' | ||
+ | draw = ImageDraw.Draw(mainimg) | ||
+ | #Clear | ||
+ | draw.rectangle([0, | ||
+ | #Copy to mainimg | ||
+ | ypos = (disp.xDot - im.size[1])/ | ||
+ | xpos = (disp.yDot - im.size[0])/ | ||
+ | print (' | ||
+ | mainimg.paste(im, | ||
+ | #Draw info text | ||
+ | ts = draw.textsize(name[1], | ||
+ | tsy = ts[1]+1 | ||
+ | oldy = -1 | ||
+ | divs = ts[0]/250 | ||
+ | for y in range(0, divs): | ||
+ | newtext = name[1][(oldy+1)*len(name[1])/ | ||
+ | #Print (divs, oldy, y, newtext) | ||
+ | oldy = y | ||
+ | draw.text((1, | ||
+ | draw.text((1, | ||
+ | draw.text((3, | ||
+ | draw.text((3, | ||
+ | draw.text((2, | ||
+ | #Draw time | ||
+ | now = datetime.datetime.now() | ||
+ | tstr = " | ||
+ | #Draw a shadow, time | ||
+ | tpx = 36 | ||
+ | tpy = 96 | ||
+ | for i in range(tpy-4, | ||
+ | draw.line([0, | ||
+ | draw.text((tpx-1, | ||
+ | draw.text((tpx-1, | ||
+ | draw.text((tpx | ||
+ | draw.text((tpx+2, | ||
+ | draw.text((tpx+2, | ||
+ | draw.text((tpx | ||
+ | draw.text((tpx | ||
+ | del draw | ||
+ | im = mainimg.transpose(Image.ROTATE_90) | ||
+ | drawtime = time.time() | ||
+ | print (' | ||
+ | listim = list(im.getdata()) | ||
+ | #Print (im.format, im.size, im.mode, len(listim)) | ||
+ | listim2 = [] | ||
+ | for y in range(0, im.size[1]): | ||
+ | for x in range(0, im.size[0]/ | ||
+ | val = 0 | ||
+ | for x8 in range(0, 8): | ||
+ | if listim[(im.size[1]-y-1)*im.size[0] + x*8 + (7-x8)] > 128: | ||
+ | #Print (x, | ||
+ | val = val | 0x01 << x8 | ||
+ | else: | ||
+ | #Print (x, | ||
+ | pass | ||
+ | #Print val | ||
+ | listim2.append(val) | ||
+ | for x in range(0, | ||
+ | | ||
+ | #Print len(listim2) | ||
+ | convtime = time.time() | ||
+ | print (' | ||
+ | ypos = 0 | ||
+ | xpos = 0 | ||
+ | disp.EPD_Dis_Part(xpos, | ||
+ | ypos+im.size[1]-1, | ||
+ | # | ||
+ | uploadtime = time.time() | ||
+ | print (' | ||
+ | except IOError as ex: | ||
+ | print (' | ||
+ | </ | ||
+ | |||
+ | === Mechanical Drivers === | ||
+ | == Relay == | ||
+ | |||
+ | Relays are electromechanical devices that use electromagnets to connect or disconnect plates of a switch. Relays are used to control high power circuits with low power circuits. Circuits are mechanically isolated and thus protect logic control. Relays are used in household appliance automation, lighting and climate control. | ||
+ | |||
+ | <figure label> | ||
+ | {{ : | ||
+ | < | ||
+ | </ | ||
+ | |||
+ | <figure label> | ||
+ | {{ : | ||
+ | < | ||
+ | </ | ||
+ | |||
+ | The example code: | ||
+ | <code Python> | ||
+ | #Raspberry Pi Python sample code | ||
+ | |||
+ | import RPi.GPIO as GPIO | ||
+ | import time | ||
+ | |||
+ | REL = 18 #GPIO04 port | ||
+ | |||
+ | GPIO.setmode(GPIO.BCM) | ||
+ | GPIO.setwarnings(False) | ||
+ | GPIO.setup(REL, | ||
+ | print ("REL on") | ||
+ | GPIO.output(REL, | ||
+ | time.sleep(1) | ||
+ | print ("REL off") | ||
+ | GPIO.output(REL, | ||
+ | </ | ||
+ | |||
+ | == Solenoid == | ||
+ | Solenoids are devices that use electromagnets to pull or push iron or steel core. They are used as linear actuators for locking mechanisms indoors, pneumatic and hydraulic valves and in-car starter systems. | ||
+ | |||
+ | Solenoids and relays both use electromagnets and connecting them to Arduino is very similar. Coils need a lot of power, and they are usually attached to the power source of the circuit. Turning the power of the coil off makes the electromagnetic field to collapse and creates very high voltage. For the semiconductor devices protection, a shunt diode is used to channel the overvoltage. For extra safety, optoisolator can be used. | ||
+ | |||
+ | <figure label> | ||
+ | {{ : | ||
+ | < | ||
+ | </ | ||
+ | |||
+ | <figure label> | ||
+ | {{ : | ||
+ | < | ||
+ | </ | ||
+ | |||
+ | The example code: | ||
+ | <code Python> | ||
+ | #Raspberry Pi Python sample code | ||
+ | |||
+ | import RPi.GPIO as GPIO | ||
+ | import time | ||
+ | |||
+ | SOL = 18 #GPIO04 port | ||
+ | |||
+ | GPIO.setmode(GPIO.BCM) | ||
+ | GPIO.setwarnings(False) | ||
+ | GPIO.setup(SOL, | ||
+ | print ("SOL on") | ||
+ | GPIO.output(SOL, | ||
+ | time.sleep(1) | ||
+ | print ("SOL off") | ||
+ | GPIO.output(SOL, | ||
+ | </ | ||
+ | |||
+ | == DC Motor (One Direction) == | ||
+ | An electric motor is an electro-technical device which can turn electrical energy into mechanical energy; motor turns because of the electricity that flows in its winding. Electric motors have seen many technical solutions over the year from which the simplest is the permanent-magnet DC motor. | ||
+ | |||
+ | DC motor is a device which converts direct current into the mechanical rotation. DC motor consists of permanent magnets in stator and coils in the rotor. By applying the current to coils, the electromagnetic field is created, and the rotor tries to align itself to the magnetic field. Each coil is connected to a commutator, which in turns supplies coils with current, thus ensuring continuous rotation. DC motors are widely used in power tools, toys, electric cars, robots, etc. | ||
+ | |||
+ | <figure label> | ||
+ | {{ : | ||
+ | < | ||
+ | </ | ||
+ | |||
+ | <figure label> | ||
+ | {{ : | ||
+ | < | ||
+ | </ | ||
+ | |||
+ | <code Python> | ||
+ | #Raspberry Pi Python sample code | ||
+ | |||
+ | import RPi.GPIO as GPIO | ||
+ | import time | ||
+ | |||
+ | DCM = 18 #GPIO04 port | ||
+ | |||
+ | GPIO.setmode(GPIO.BCM) | ||
+ | GPIO.setwarnings(False) | ||
+ | GPIO.setup(DCM, | ||
+ | print ("DCM on") | ||
+ | GPIO.output(DCM, | ||
+ | time.sleep(1) | ||
+ | print ("DCM off") | ||
+ | GPIO.output(DCM, | ||
+ | </ | ||
+ | |||
+ | == Stepper Motor == | ||
+ | Stepper motors are motors, that can be moved by a certain angle or step. Full rotation of the motor is divided into small, equal steps. Stepper motor has many individually controlled electromagnets, | ||
+ | Example of use can be found in the source ((https:// | ||
+ | |||
+ | <figure label> | ||
+ | {{ : | ||
+ | < | ||
+ | </ | ||
+ | |||
+ | <figure label> | ||
+ | {{ : | ||
+ | < | ||
+ | </ | ||
+ | |||
+ | The example code: | ||
+ | <code Python> | ||
+ | #Raspberry Pi Python sample code | ||
+ | #From https:// | ||
+ | |||
+ | from time import sleep | ||
+ | import RPi.GPIO as GPIO | ||
+ | |||
+ | DIR = 20 # | ||
+ | STEP = 21 #Step GPIO Pin | ||
+ | CW = 1 # | ||
+ | CCW = 0 # | ||
+ | SPR = 48 # | ||
+ | |||
+ | GPIO.setmode(GPIO.BCM) | ||
+ | GPIO.setup(DIR, | ||
+ | GPIO.setup(STEP, | ||
+ | GPIO.output(DIR, | ||
+ | |||
+ | step_count = SPR | ||
+ | delay = .0208 | ||
+ | |||
+ | for x in range(step_count): | ||
+ | GPIO.output(STEP, | ||
+ | sleep(delay) | ||
+ | GPIO.output(STEP, | ||
+ | sleep(delay) | ||
+ | |||
+ | sleep(.5) | ||
+ | GPIO.output(DIR, | ||
+ | for x in range(step_count): | ||
+ | | ||
+ | | ||
+ | | ||
+ | | ||
+ | |||
+ | GPIO.cleanup() | ||
+ | </ | ||
+ | This code may result in motor vibration and jerky motion especially at low speeds. | ||
+ | < | ||
+ | MODE = (14, 15, 18) # | ||
+ | GPIO.setup(MODE, | ||
+ | RESOLUTION = {' | ||
+ | ' | ||
+ | ' | ||
+ | ' | ||
+ | ' | ||
+ | ' | ||
+ | GPIO.output(MODE, | ||
+ | |||
+ | step_count = SPR * 32 | ||
+ | delay = .0208 / 32 | ||
+ | </ | ||
+ | |||
+ | |||
+ | |||
+ | ==== ==== | ||
+ | <box # | ||
+ | <box # | ||
+ | ==== Raspberry Pi OS Guide ==== | ||
+ | <box # | ||
+ | <box # | ||
+ | |||
+ | === Supported Operating Systems (OS) === | ||
+ | Raspberry Pi all models are based on ARM processors which are typically quad-core Cortex-A7 CPUs. This means that most of popular multitasking OS systems can be uploaded and used to create and develop user software operations. The list of supported OS systems contains Linux, Windows and thirty part OS systems. The following list of figures of OS are specially designed for Raspberry Pi boards: | ||
+ | <figure label> | ||
+ | {{ : | ||
+ | </ | ||
+ | <figure label> | ||
+ | {{ : | ||
+ | </ | ||
+ | <figure label> | ||
+ | {{ : | ||
+ | </ | ||
+ | <figure label> | ||
+ | {{ : | ||
+ | </ | ||
+ | <figure label> | ||
+ | {{ : | ||
+ | </ | ||
+ | <figure label> | ||
+ | {{ : | ||
+ | </ | ||
+ | <figure label> | ||
+ | {{ : | ||
+ | </ | ||
+ | <figure label> | ||
+ | {{ : | ||
+ | </ | ||
+ | |||
+ | Before start installing the OS system on the Raspberry Pi board developer must prepare his hardware for it ((https:// | ||
+ | * Raspberry Pi board, | ||
+ | * monitor or TV with HDMI port, | ||
+ | * HDMI cable, | ||
+ | * USB keyboard, | ||
+ | * USB mouse, | ||
+ | * power supply, | ||
+ | * at least 8 GB micro SD card (C10 class is welcome). | ||
+ | Connecting all establishes the minimum PC desktop kit which will allow to install and run the selected OS system on the SD card. | ||
+ | |||
+ | === Downloading OS System === | ||
+ | There are few ways to get the right OS system for Raspberry Pi board: | ||
+ | * buy pre-installed SD card from RS ((https:// | ||
+ | * install Raspbian with NOOBS ((https:// | ||
+ | * download Raspbian image directly from Raspberry Pi software repository ((https:// | ||
+ | * download the Windows 10 IOT OS from Microsoft Windows Insider Preview ((https:// | ||
+ | |||
+ | ===Other Raspberry OS Systems=== | ||
+ | For other then Windows and NOOBS systems use the Etcher SD ((https:// | ||
+ | <figure label> | ||
+ | {{ : | ||
+ | </ | ||
+ | ==== ==== | ||
+ | <box # | ||
+ | <box # | ||
+ | ==== Programming Fundamentals Raspbian OS ==== | ||
+ | <box # | ||
+ | <box # | ||
+ | |||
+ | === Installing the Raspbian OS === | ||
+ | To install the OS system on SD card the best way is to use specially designed software which will provide SD card formatting tool. | ||
+ | ==Step 1== | ||
+ | Download and install the **SD Formatter** ((https:// | ||
+ | Run the SD Formatter tool. | ||
+ | <figure label> | ||
+ | {{ : | ||
+ | </ | ||
+ | ==Step 2== | ||
+ | Insert the SD card into the computer SD card reader. | ||
+ | ==Step 3== | ||
+ | Run the SD Formatter, select the drive letter for the SD card and format it. | ||
+ | ==Step 4== | ||
+ | Simply drag and drop the extracted NOOBS OS image files from unzipped NOOBS folder onto the SD card drive. The necessary files will be transferred to the SD card. | ||
+ | ==Step 5== | ||
+ | Gently remove SD card from the reader and push it into the Raspberry Pi SD card slot. | ||
+ | ==Step 6== | ||
+ | Power on the Raspberry Pi board and follow its instructions. | ||
+ | |||
+ | After the board reboot the Raspbian screen displays. | ||
+ | <figure label> | ||
+ | {{ : | ||
+ | </ | ||
+ | === === | ||
+ | <box # | ||
+ | <box # | ||
+ | === Raspberry Pi Python Programming Guide === | ||
+ | <box # | ||
+ | <box # | ||
+ | |||
+ | == Python Language == | ||
+ | Python belongs to the high-level programming languages class which was first time developed by Guido van Rossum in 1991. The Python is similar to C++, C# or Java programming languages. It is very useable with a clean syntax and easy to learn even for programming beginners. | ||
+ | |||
+ | Raspberry Raspbian OS is shipped with pre installed two versions of Python language: Python2 and Python3 which are available from the Raspbian Menu. | ||
+ | <figure label> | ||
+ | {{ : | ||
+ | </ | ||
+ | Choosing the Python version from the menu, the command window with cursor opens. | ||
+ | < | ||
+ | Python 3.5.2 (v3.5.2: | ||
+ | [MSC v.1900 64 bit (AMD64)] on Win32 | ||
+ | Type " | ||
+ | >>> | ||
+ | </ | ||
+ | |||
+ | To test the simply program "// | ||
+ | < | ||
+ | Python 3.5.2 (v3.5.2: | ||
+ | [MSC v.1900 64 bit (AMD64)] on Win32 | ||
+ | Type " | ||
+ | >>> | ||
+ | Hello World! | ||
+ | >>> | ||
+ | </ | ||
+ | |||
+ | Writing the same code in C language will look following: | ||
+ | <code c> | ||
+ | #include < | ||
+ | int main() | ||
+ | { | ||
+ | printf (" | ||
+ | return 0; | ||
+ | } | ||
+ | </ | ||
+ | |||
+ | ==Python Program Features== | ||
+ | Python can automate tasks using the batch commands renaming and move large amounts of files like shell scripts. It can be used as a command line with IDLE, Python’s REPL (read, eval, print, loop) functions. However, there are more useful tasks which can be done with Python. For example, Python can be used to program things like: | ||
+ | * web applications, | ||
+ | * desktop applications and utilities, | ||
+ | * special GUIs, | ||
+ | * small databases, | ||
+ | * 2D games. | ||
+ | Because Python stays very popular, it has a large collection of libraries, which speeds up the development process. There exist libraries for – game programming, | ||
+ | |||
+ | Many of the programmings stuff in C language can also be programmed in Python. Python is generally slower at computations regarding the C compiler, but its ease for use, which makes Python a very popular tool for prototyping programs and designing applications which are not computationally intensive. One of the best Python tutorials can be found in the book: " | ||
+ | |||
+ | ==Installing and Updating Python== | ||
+ | Python 2 and Python 3 come pre-installed on Raspbian OS systems, but if necessary to install Python on another Linux OS or to update it, the simple commands can be executed at the command prompt: | ||
+ | < | ||
+ | sudo apt-get install python3 | ||
+ | </ | ||
+ | Installs or updates Python 3. | ||
+ | < | ||
+ | sudo apt-get install python | ||
+ | </ | ||
+ | Installs or updates Python 2. | ||
+ | |||
+ | ==Opening the PYTHON REPL== | ||
+ | To access the Python REPL (where the user can type Python commands just like the command line) the user can enter python or python3 commands depending on which version of Raspbian to use in the command prompt. | ||
+ | <figure label> | ||
+ | {{ : | ||
+ | </ | ||
+ | Pressing (CTRL-D) exits the REPL. | ||
+ | |||
+ | ==Running a Python Program== | ||
+ | To run the program without making it executable, the user must navigate to the location where the file exists and enter the command: | ||
+ | < | ||
+ | python hello-world.py | ||
+ | </ | ||
+ | |||
+ | ==Make Python File Executable== | ||
+ | Making a Python program executable allows to run the program without entering python before the file name. User can make a file executable executing the following commands in the command prompt: | ||
+ | < | ||
+ | chmod +x file-name.py | ||
+ | </ | ||
+ | Now to run the program: | ||
+ | < | ||
+ | ./ | ||
+ | </ | ||
+ | == Additional Resources for Python programming== | ||
+ | - The Python syntax and semantics: [[https:// | ||
+ | - The Python Package Index (PyPi): [[https:// | ||
+ | - The Python Standard Library: | ||
+ | <todo @pczekalski> | ||
+ | === === | ||
+ | <box # | ||
+ | <box # | ||
+ | ===Python Data Types and Variables=== | ||
+ | <box # | ||
+ | <box # | ||
+ | |||
+ | Python aims to be consistent and straightforward in the design of its syntax. The best advantage of this language is that it can dynamically set the variable types depending on values types which are set for variables. | ||
+ | |||
+ | ==Base Types== | ||
+ | Python has a wide range of data types, like many simple programming languages: | ||
+ | * number, | ||
+ | * string, | ||
+ | * list, | ||
+ | * tuple | ||
+ | * dictionary. | ||
+ | |||
+ | ==Numbers== | ||
+ | Standard Python methods are used to create the numbers: | ||
+ | <code Python> | ||
+ | var = 1234 # | ||
+ | var = ' | ||
+ | </ | ||
+ | |||
+ | Python can automatically convert types of the number from one type to another. Type can be also defined explicitly. | ||
+ | <code Python> | ||
+ | int a = 10 | ||
+ | long a = 123L | ||
+ | float a = 12.34 | ||
+ | complex a = 3.23J | ||
+ | < | ||
+ | |||
+ | ==String== | ||
+ | To define Strings use eclosing characters in quotes. | ||
+ | Python uses single quotes ', double " and triple """ | ||
+ | <code Python> | ||
+ | Name = " | ||
+ | lastName = " | ||
+ | message = """ | ||
+ | </ | ||
+ | |||
+ | ==List== | ||
+ | List contains a series of values. To declare list variables uses brackets []. | ||
+ | <code Python> | ||
+ | A = [] #Blank list variable | ||
+ | B = [1, 2, 3] #List with 3 numbers | ||
+ | C = [1, ' | ||
+ | </ | ||
+ | List are zero-based indexed. Data can be assigned to a specific element of the list using an index into the list. | ||
+ | <code Python> | ||
+ | mylist[0] = ' | ||
+ | mylist[1] = ' | ||
+ | |||
+ | print mylist[1] | ||
+ | </ | ||
+ | List aren't limited to a single dimension. | ||
+ | <code Python> | ||
+ | myTable = [[],[]] | ||
+ | </ | ||
+ | In two-dimensional array the first number is always the rows number, when the second is the columns number. | ||
+ | |||
+ | ==Tuple== | ||
+ | Python Tuples are defined as a group of values like a list and can be processed in similar ways. When assigned Tuples got the fixed size. In Python, the fixed size is immutable. The lists are dynamic and mutable. To define Tuples, parenthesis () must be used. | ||
+ | <code Python> | ||
+ | TestSet = (' | ||
+ | </ | ||
+ | |||
+ | == Dictionary== | ||
+ | To define the Dictionaries in the Python the lists of key--value pairs are used. This datatype is used to hold related information that can be associated through Keys. The Dictionary is used to extract a value based on the key name. Lists use the index numbers to access its members when dictionaries use a key. Dictionaries generally are used to sort, iterate and compare data. | ||
+ | |||
+ | To define the Dictionaries the braces ({}) are used with pairs separated by a comma (,) and the key values associated with a colon (:). Dictionaries Keys must be unique. | ||
+ | <code Python> | ||
+ | box_nbr = {' | ||
+ | box_nbr[' | ||
+ | print (box nbr[' | ||
+ | box_nbr[' | ||
+ | print (box_nbr.keys()) | ||
+ | print (' | ||
+ | #This returns true | ||
+ | </ | ||
+ | |||
+ | |||
+ | All variables in Python hold references to objects, and are passed to functions. Function can't change the value of variable references in its body. The object' | ||
+ | < | ||
+ | >>> | ||
+ | >>> | ||
+ | al.append(' | ||
+ | print al | ||
+ | |||
+ | >>> | ||
+ | [' | ||
+ | >>> | ||
+ | [' | ||
+ | </ | ||
+ | === === | ||
+ | <box # | ||
+ | <box # | ||
+ | ===Python Program Control Structures=== | ||
+ | <box # | ||
+ | <box # | ||
+ | |||
+ | ==if Statements== | ||
+ | If an expression returns //TRUE// statements are carried out. Otherwise they aren' | ||
+ | <code Python> | ||
+ | if expression: | ||
+ | statements | ||
+ | </ | ||
+ | |||
+ | Sample: | ||
+ | <code Python> | ||
+ | no = 11 | ||
+ | if no >10: | ||
+ | print (" | ||
+ | if no <=30 | ||
+ | | ||
+ | </ | ||
+ | Output: | ||
+ | < | ||
+ | >>> | ||
+ | Greater than 10 | ||
+ | Between 10 and 30 | ||
+ | >>> | ||
+ | </ | ||
+ | |||
+ | ==else Statements== | ||
+ | An //else// statement follows an //if// statement and contains code that is called when the if statement is //FALSE//. | ||
+ | <code Python> | ||
+ | x = 2 | ||
+ | if x == 6 | ||
+ | printf (" | ||
+ | else: | ||
+ | printf (" | ||
+ | </ | ||
+ | |||
+ | ==elif Statements== | ||
+ | The //elif// (shortcut of //else if//) statement is used when changing //if// and //else// statements. A series of // | ||
+ | <code Python> | ||
+ | num = 12 | ||
+ | if num == 5: | ||
+ | printf (" | ||
+ | elif num == 4: | ||
+ | printf (" | ||
+ | elif num == 3: | ||
+ | printf (" | ||
+ | else: | ||
+ | printf (" | ||
+ | </ | ||
+ | Output: | ||
+ | < | ||
+ | >>> | ||
+ | | ||
+ | >>> | ||
+ | </ | ||
+ | |||
+ | ==Boolean Logic== | ||
+ | Python uses logic operators like //AND//, //OR// and //NOT//. | ||
+ | |||
+ | The //AND// operator uses two arguments, and evaluates to //TRUE// if, and only if, both of the arguments are //TRUE//. Otherwise, it evaluates to //FALSE//. | ||
+ | <code Python> | ||
+ | >>> | ||
+ | True | ||
+ | >>> | ||
+ | False | ||
+ | >>> | ||
+ | False | ||
+ | >>> | ||
+ | False | ||
+ | >>> | ||
+ | </ | ||
+ | |||
+ | Boolean operator **or** uses two arguments, and evaluates as //TRUE// if either (or both) of its arguments are //TRUE//, and //FALSE// if both arguments are //FALSE//. | ||
+ | |||
+ | The result of //NOT TRUE// is //FALSE//, and // NOT FALSE// goes to //TRUE//. | ||
+ | <code Python> | ||
+ | >>> | ||
+ | False | ||
+ | >>> | ||
+ | True | ||
+ | >>> | ||
+ | </ | ||
+ | |||
+ | == Operator Precedence== | ||
+ | Operator Precedence uses mathematical idea of operation order, e.g. multiplication begin performed before addition. | ||
+ | |||
+ | <code Python> | ||
+ | >>> | ||
+ | True | ||
+ | >>> | ||
+ | False | ||
+ | >>> | ||
+ | >>> | ||
+ | >>> | ||
+ | </ | ||
+ | |||
+ | |||
+ | |||
+ | === === | ||
+ | <box # | ||
+ | <box # | ||
+ | ===Python Looping=== | ||
+ | <box # | ||
+ | <box # | ||
+ | |||
+ | == while Loop== | ||
+ | An //if// statement is run once if its condition evaluates to //TRUE//, and never if it evaluates to //FALSE//. | ||
+ | |||
+ | A //while// statement is similar, except that it can be run more than once. The statements inside it are repeatedly executed, as long as the condition holds. Once it evaluates to //FALSE//, the next section of code is executed. | ||
+ | <code Python> | ||
+ | i = 1 | ||
+ | while i<=4: | ||
+ | print (i) | ||
+ | i+=1 | ||
+ | print (' | ||
+ | </ | ||
+ | |||
+ | Output: | ||
+ | < | ||
+ | >>> | ||
+ | 1 | ||
+ | 2 | ||
+ | 3 | ||
+ | 4 | ||
+ | End | ||
+ | >>> | ||
+ | </ | ||
+ | |||
+ | The **infinite loop** is a particular kind of the //while// loop, it never stops running. Its condition always remains //TRUE//. | ||
+ | |||
+ | <code Python> | ||
+ | while 1 == 1: | ||
+ | print ('in the loop') | ||
+ | </ | ||
+ | |||
+ | To end the //while// loop prematurely, | ||
+ | When encountered inside a loop, the break statement causes the loop to finish immediately. | ||
+ | <code Python> | ||
+ | i = 0 | ||
+ | while 1==1: | ||
+ | print (i) | ||
+ | i += 1 | ||
+ | if i >=3: | ||
+ | print(' | ||
+ | break; | ||
+ | print (' | ||
+ | </ | ||
+ | |||
+ | Output: | ||
+ | < | ||
+ | >>> | ||
+ | 0 | ||
+ | 1 | ||
+ | 2 | ||
+ | 3 | ||
+ | breaking | ||
+ | finished | ||
+ | >>> | ||
+ | </ | ||
+ | |||
+ | Another statement that can be used within loops is **continue**. | ||
+ | |||
+ | Unlike break, continue jumps back to the top of the loop, rather than stopping it. | ||
+ | <code Python> | ||
+ | i = 0 | ||
+ | while True: | ||
+ | i+=1 | ||
+ | if i == 2: | ||
+ | printf (' | ||
+ | continue | ||
+ | if i == 5: | ||
+ | print (' | ||
+ | break | ||
+ | print (i) | ||
+ | print (' | ||
+ | </ | ||
+ | |||
+ | Output: | ||
+ | < | ||
+ | >>> | ||
+ | 1 | ||
+ | skipping 2 | ||
+ | 3 | ||
+ | 4 | ||
+ | breaking | ||
+ | finished | ||
+ | >>> | ||
+ | </ | ||
+ | |||
+ | == for Loop== | ||
+ | |||
+ | <code Python> | ||
+ | n = 9 | ||
+ | for i in range (1,5): | ||
+ | ml = n * i | ||
+ | print ("{} * {} = {}" | ||
+ | </ | ||
+ | |||
+ | Output: | ||
+ | < | ||
+ | >>> | ||
+ | 9 * 1 = 9 | ||
+ | 9 * 2 = 18 | ||
+ | 9 * 3 = 27 | ||
+ | 9 * 4 = 36 | ||
+ | >>> | ||
+ | </ | ||
+ | |||
+ | === === | ||
+ | <box # | ||
+ | <box # | ||
+ | === Python Sub-Programs === | ||
+ | <box # | ||
+ | <box # | ||
+ | |||
+ | ==Subprograms== | ||
+ | One of the most important in mathematics concept is to use functions. Functions in computer languages implement mathematical functions. The executing function produces one or more results, which are dependent by the parameters passed to it. | ||
+ | |||
+ | In general, a function is a structuring element in the programming language which groups a set of statements so they can be called more than once in a program. Programming without functions will need to reuse code by copying it and changing its different context. Using functions enhances the comprehensibility and quality of the program. It also lowers the memory usage, development cost and maintenance of the software. | ||
+ | |||
+ | Different naming is used for functions in programming languages, e.g. as subroutines, | ||
+ | |||
+ | Python language defines function by a //def// statement. The function syntax looks: | ||
+ | < | ||
+ | def function-name(Parameter list): | ||
+ | statements, i.e. the function body | ||
+ | </ | ||
+ | Function bodie can contain one or more return statement. It can be situated anywhere in the function body. A return statement ends the function execution and returns the result, i.e. to the caller. If the return statement does not contain expression, the value //None// is returned. | ||
+ | <code Python> | ||
+ | def Fahrenheit(T_in_celsius): | ||
+ | """ | ||
+ | return (T_in_celsius * 9 / 5) + 32 | ||
+ | |||
+ | for t in (22.6, 25.8, 27.3, 29.8): | ||
+ | print(t, ": ", fahrenheit(t)) | ||
+ | </ | ||
+ | Output: | ||
+ | < | ||
+ | >>> | ||
+ | 22.6 : 72.68 | ||
+ | 25.8 : 78.44 | ||
+ | 27.3 : 81.14 | ||
+ | 29.8 : 85.64 | ||
+ | >>> | ||
+ | </ | ||
+ | |||
+ | ==Optional Parameters== | ||
+ | Functions can be called with optional parameters, also named default parameters. If function is called without parameters the default values are used. The following code greets a person. If no person name is defined, it greets everybody: | ||
+ | <code Python> | ||
+ | def Hello(name=" | ||
+ | """ | ||
+ | print(" | ||
+ | |||
+ | Hello(" | ||
+ | Hello() | ||
+ | </ | ||
+ | |||
+ | Output: | ||
+ | < | ||
+ | >>> | ||
+ | Hello George! | ||
+ | Hello everybody! | ||
+ | >>> | ||
+ | </ | ||
+ | |||
+ | ==Docstrings== | ||
+ | The string is usually the first statement in the function body, which can be accessed with function_name.doc. | ||
+ | This is Docstring statement. | ||
+ | <code Python> | ||
+ | def Hello(name=" | ||
+ | """ | ||
+ | print(" | ||
+ | print(" | ||
+ | </ | ||
+ | |||
+ | Output: | ||
+ | < | ||
+ | >>> | ||
+ | The function Hello docstring: | ||
+ | >>> | ||
+ | </ | ||
+ | |||
+ | ==Keyword Parameters== | ||
+ | The alternative way to make function calls is to use keyword parameters. The function definition stay unchanged. | ||
+ | <code Python> | ||
+ | def sumsub(a, b, c=0, d=0): | ||
+ | return a - b + c - d | ||
+ | print(sumsub(12, | ||
+ | print(sumsub(42, | ||
+ | </ | ||
+ | |||
+ | Only keyword parameters are valid, which are not used as positional arguments. If keyword parameters don't exist, the next call to the function will need all four arguments, even if the //c// needs just the default value: | ||
+ | <code Python> | ||
+ | print(sumsub(42, | ||
+ | </ | ||
+ | |||
+ | ==Return Values== | ||
+ | In above examples, the return statement exist in sumsub but not in //Hello// function. The return statement is not mandatory. If explicitly return statement doesn' | ||
+ | <code Python> | ||
+ | def no_return(x, | ||
+ | c = x + y | ||
+ | res = no_return(4, | ||
+ | print(res) | ||
+ | </ | ||
+ | |||
+ | Any result will not be displayed in: | ||
+ | < | ||
+ | >>> | ||
+ | </ | ||
+ | |||
+ | Executing this script, the //None// will be printed. If a function doesn' | ||
+ | <code Python> | ||
+ | def empty_return(x, | ||
+ | c = x + y | ||
+ | return | ||
+ | res = empty_return(4, | ||
+ | print(res) | ||
+ | </ | ||
+ | |||
+ | Otherwise the expression value following return will be returned. In this example 11 will be printed: | ||
+ | <code Python> | ||
+ | def return_sum(x, | ||
+ | c = x + y | ||
+ | return c | ||
+ | res = return_sum(6, | ||
+ | print(res) | ||
+ | </ | ||
+ | |||
+ | Output: | ||
+ | < | ||
+ | >>> | ||
+ | 9 | ||
+ | >>> | ||
+ | </ | ||
+ | |||
+ | ==Multiple Values Returning== | ||
+ | Any function can return only one object. An object can be a numerical value -- integer, float, list or a dictionary. To return i.e. three integer values, we can return a list or a tuple with these three integer values. It means that function can indirectly return multiple values. This following example calculates the Fibonacci boundary for a positive number, returns a 2-tuple. The Largest Fibonacci Number smaller than //x// is the first and the Smallest Fibonacci Number larger than //x// is next. The return value is stored via unpacking into the variables lub and sup: | ||
+ | <code Python> | ||
+ | def fib_intervall(x): | ||
+ | """ | ||
+ | Fibonacci number, higher than x""" | ||
+ | if x < 0: | ||
+ | return -1 | ||
+ | (old, new, lub) = (0,1,0) | ||
+ | while True: | ||
+ | if new < x: | ||
+ | lub = new | ||
+ | (old,new) = (new, | ||
+ | else: | ||
+ | return (lub, new) | ||
+ | | ||
+ | while True: | ||
+ | x = int(input(" | ||
+ | if x <= 0: | ||
+ | break | ||
+ | (lub, sup) = fib_intervall(x) | ||
+ | print(" | ||
+ | print(" | ||
+ | </ | ||
+ | |||
+ | |||
+ | ==== ==== | ||
+ | <box # | ||
+ | <box # | ||
+ | ==== Programming Fundamentals Windows 10 IOT Core ==== | ||
+ | <box # | ||
+ | <box # | ||
+ | |||
+ | === Installing the Windows 10 IOT Core === | ||
+ | Microsoft Windows 10 IOT OS system is available for download from Windows Insider Preview Downloads page ((https:// | ||
+ | ===Step 1=== | ||
+ | Register into the Microsoft Insider Program. To download images of the Microsoft IOT Core user must be logged into Microsoft Insider Program web page. | ||
+ | ===Step 2=== | ||
+ | On the download page, User must choose which OS edition he wants to use in his project ieg. Windows 10 IOT Core Insider preview -- build 17083 or 17035. The core numbers are changing depending on the latest developer editions available in the Microsoft repository. Microsoft IOT development policy is straightly tied with the latest Visual Studio environment. To fully use its power, users are asked to use the latest Visual Studio and Windows 10 IOT core builds in the development process synchronously. The Windows 10 IOT Core platform is still under development and improvement. | ||
+ | <figure label> | ||
+ | {{ : | ||
+ | </ | ||
+ | ===Step 3=== | ||
+ | Install the right Windows10_InsiderPreview_IoTCore_RPi_ARM32_en-us_17035.iso image on your Windows 10 PC. This package installs the //Windows IOT Core Image Helper// application and stores the latest Raspberry Pi Windows 10 core image flash.ffu file into the // | ||
+ | ===Step 4=== | ||
+ | Insert the SD card to your computer SD cards reader slot. | ||
+ | ===Step 5=== | ||
+ | Run the Windows IOT Core Image Helper and follow its instructions -- select the SD card drive letter, select the right FFU image in the // | ||
+ | <figure label> | ||
+ | {{ : | ||
+ | </ | ||
+ | ===Step 6=== | ||
+ | Start formatting the SD card and install the FFU image on it. | ||
+ | ===Step 7=== | ||
+ | Gently remove SD card from the reader and push it into the Raspberry Pi SD card slot. | ||
+ | ===Step 8=== | ||
+ | Power on the Raspberry Pi board and follow the Windows 10 Core setup commands configuring the Windows 10 Core features. | ||
+ | |||
+ | After the board reboot the Main Windows 10 Core screen displays: | ||
+ | <figure label> | ||
+ | {{ : | ||
+ | </ | ||
+ | === === | ||
+ | <box # | ||
+ | <box # | ||
+ | === Raspberry Pi Programming Guide === | ||
+ | <box # | ||
+ | <box # | ||
+ | This chapter describes the typical programming technics used in Raspberry Pi boards developing projects. | ||
+ | |||
+ | == Raspberry Pi Under Windows 10 IoT Core == | ||
+ | To create and develop control applications on the Raspberry Pi boards needs the following development environment: | ||
+ | * PC with Windows 10 System installed, | ||
+ | * Visual Studio 2015 or higher, | ||
+ | * Raspberry PI 2 or 3 board with Windows 10 IoT Core installed, | ||
+ | * configured TCP/IP network for Raspberry Pi and Windows 10 Desktop computer (Local LAN or WiFi subnet), | ||
+ | |||
+ | Programming skills needed: | ||
+ | * C# language knowledge, | ||
+ | * XML/XAML language knowledge, | ||
+ | * Windows API understanding. | ||
+ | |||
+ | For better development Raspberry applications, | ||
+ | <figure label> | ||
+ | {{ : | ||
+ | </ | ||
+ | To write and develop applications under Windows 10 IoT Core developer must possess basic knowledge of how Windows operating system interacts with User applications. The major advantage of using Windows 10 IoT Core is that Microsoft concept based on use the same Kernel API available on different hardware platforms -- desktop PCs, IoT boards suitable to run Windows Core, Tablets, phones etc. It reduces development costs due to the unifying system environment, | ||
+ | |||
+ | == Configuring the Windows 10 IoT Core Platform == | ||
+ | After installing the Windows 10 IoT Core, the developer must configure IoT platform using Windows Device Portal (WDP). | ||
+ | <figure label> | ||
+ | {{ : | ||
+ | </ | ||
+ | IoT board can be managed using any Internet browser -- Chrome, Microsoft Edge, Firefox etc. To open the WDB portal on the IoT board user must enter the board IP address -- IPaddress: | ||
+ | |||
+ | ==Step 1== | ||
+ | In the **Device Settings** user is recommended to **Change your device name**. The default name is **minwinpc**. The aim to change it is that if a user uses many of the IoT devices connected to the same network segment, it is difficult to recognise which role each device is set for. Enumerating IoT devices will show boards with the same name but with different IP addresses. Proper naming will make it easy to know what role each device plays. | ||
+ | |||
+ | ==Step 2== | ||
+ | Because RPI boards don't have their own RTC clock modules, Windows 10 IoT Core sets the time using the NTP services during its work. So very important in the industrial implementations and in a case when the time is important in developed applications is to set the proper time zone for the board. In the **Device settings** user is recommended to select proper **Time zone** | ||
+ | |||
+ | ==Step 3== | ||
+ | Security reasons -- the default password for the newly flashed device is **p@ssw0rd**. It is strongly recommended right after the first board boot to change it -- to set it unique! It will prevent the IoT device from remote hacking. The password can be changed in **Device Settings** tab. | ||
+ | |||
+ | ==Step 4== | ||
+ | The Windows 10 IoT Core comes with **Cortana** service ready. If the board is equipped with microphone and speakers, it is always possible to turn the Cortana service on for voice commands communication with the board. | ||
+ | |||
+ | ==Step 5== | ||
+ | If the IoT board needs special hardware connected to it then in the **Devices/ | ||
+ | <figure label> | ||
+ | {{ : | ||
+ | </ | ||
+ | |||
+ | ==Step 6== | ||
+ | Raspberry Pi boards 1/2/3 are equipped with network connection modules. In case if the board under Windows 10 IoT Core is connected to LAN RJ45 connector the IP number can be set via DHCP server. In case if user wants to use WiFi connection or to activate Bluetooth then he can do it directly on the board main display or manage them via Windows Device Portal. | ||
+ | <figure label> | ||
+ | {{ : | ||
+ | </ | ||
+ | <figure label> | ||
+ | {{ : | ||
+ | </ | ||
+ | |||
+ | ==Step 7== | ||
+ | Security. In a case when IoT device must be protected for remote hacking one of solutions is to use Trusted Platform Modules (TPM) module following ISO/IEC 11889 standards for a secure cryptoprocessor, | ||
+ | |||
+ | * generate and store the cryptographic keys; | ||
+ | * use the TPM unique RSA key technology for platform device authentication, | ||
+ | * help ensure platform integrity. | ||
+ | |||
+ | The most common TPM functions are used for system integrity measurements, | ||
+ | <figure label> | ||
+ | {{ : | ||
+ | </ | ||
+ | Under the TPM Configuration tab in the Windows Device, Portal user can select the right communication protocol for the TPM module installed in the Raspberry Pi board. Then appropriate driver for the TPM module can be installed in the Device Manager tab. | ||
+ | <figure label> | ||
+ | {{ : | ||
+ | </ | ||
+ | === === | ||
+ | <box # | ||
+ | <box # | ||
+ | ===RPI Windows 10 IoT Sample Project === | ||
+ | <box # | ||
+ | <box # | ||
+ | |||
+ | == Create Simple Hello World Application for Raspberry Pi Board === | ||
+ | To create simple Hello Word application under Windows 10 IoT Core the Visual Studio 2015 or higher is needed. Visual Studio must be installed with the Universal Windows Platform development extension. | ||
+ | <figure label> | ||
+ | {{ : | ||
+ | </ | ||
+ | |||
+ | ==Step 1== | ||
+ | Create new UWP project choosing the Windows Universal/ | ||
+ | <figure label> | ||
+ | {{ : | ||
+ | </ | ||
+ | |||
+ | ==Step 2== | ||
+ | Select target version (according to Raspberry Pi Windows 10 IoT Core build version) | ||
+ | <figure label> | ||
+ | {{ : | ||
+ | </ | ||
+ | |||
+ | ==Step 3== | ||
+ | Create Hello solution. | ||
+ | <figure label> | ||
+ | {{ : | ||
+ | </ | ||
+ | |||
+ | ==Step 4== | ||
+ | Design the application screen modifying the MainPage.xaml file. To add different screen features use the Toolbox/All XAML controls. | ||
+ | <figure label> | ||
+ | {{ : | ||
+ | </ | ||
+ | |||
+ | ==Step 5== | ||
+ | Modify the MainPage.cs file content if you need controls events programming. | ||
+ | <figure label> | ||
+ | {{ : | ||
+ | </ | ||
+ | |||
+ | ==Step 6== | ||
+ | Compile and run Hello solution. Choosing the Solution Platform to the x86 user will be able to debug and run Hello application on the computers desktop emulator. This step is useful for program touchscreen design but is not capable of testing the sensors and controls programming due to software emulator restrictions. | ||
+ | <figure label> | ||
+ | {{ : | ||
+ | </ | ||
+ | |||
+ | Software emulators aren't capable of simulating their behaviour. To use sensors and controls instead, the Solution Platform must be changed to the ARM platform in the VC Solution Configuration property. To debug it application package must be then transferred to the real IoT device. | ||
+ | <figure label> | ||
+ | {{ : | ||
+ | </ | ||
+ | |||
+ | ==Step 7== | ||
+ | To deploy and debug the application package on the real IoT device user must configure the debug application settings. In the Debug property page user must enter the proper Remote IoT device IP number. | ||
+ | <figure label> | ||
+ | {{ : | ||
+ | </ | ||
+ | |||
+ | ==Step 8== | ||
+ | Start debugging application and after deploy application package to the board SD card it will be displayed on the monitor. | ||
+ | <figure label> | ||
+ | {{ : | ||
+ | </ | ||
+ | === === | ||
+ | <box # | ||
+ | <box # | ||
+ | ===C# Variables and Data Types=== | ||
+ | <box # | ||
+ | <box # | ||
+ | |||
+ | |||
+ | The C# ((https:// | ||
+ | * value types, | ||
+ | * reference types, | ||
+ | * pointer types. | ||
+ | |||
+ | ==Value Type Variables== | ||
+ | Value type variables can assign a value directly. The class System.ValueType defines them. | ||
+ | |||
+ | The value types directly contain data. Value types may be: //int//, //char// and //float//, storing numbers, strings or floating point values. When an int type is declared, the system allocates memory to store its value. | ||
+ | |||
+ | The available value types list in C# is presented following: | ||
+ | <table C# Value/O> | ||
+ | < | ||
+ | ^ Type ^ Represents ^ Range ^ Default Value ^ | ||
+ | | bool | Boolean value | True or False |False | | ||
+ | | byte | 8-bit unsigned integer | 0 to 255 | 0 | | ||
+ | | char | 16-bit Unicode character | U +0000 to U +ffff |' | ||
+ | | decimal | 128-bit precise decimal values with 28-29 significant digits | (--7.9 × 10E28 to 7.9 × 10E28) / 10E0 to 28 | 0.0M | | ||
+ | | double | 64-bit double-precision floating point type | (+/--)5.0 × 10E--324 to (+/--)1.7 × 10E308 | 0.0D | | ||
+ | | float | 32-bit single-precision floating point type | --3.4 × 10E38 to + 3.4 × 10E38 | 0.0F | | ||
+ | | int | 32-bit signed integer type | --2 147 483 648 to 2 147 483 647 | 0 | | ||
+ | | long | 64-bit signed integer type | --9 223 372 036 854 775 808 to 9 223 372 036 854 775 807 | 0L | | ||
+ | | sbyte | 8-bit signed integer type | --128 to 127 | 0 | | ||
+ | | short | 16-bit signed integer type | --32 768 to 32 767 | 0 | | ||
+ | | uint | 32-bit unsigned integer type | 0 to 4 294 967 295 | 0 | | ||
+ | | ulong | 64-bit unsigned integer type | 0 to 18 446 744 073 709 551 615 | 0 | | ||
+ | | ushort | 16-bit unsigned integer type | 0 to 65 535 | 0 | | ||
+ | </ | ||
+ | |||
+ | ==Reference Type== | ||
+ | The reference types don't contain the actual data stored in a variable. They contain a reference to the variables. | ||
+ | |||
+ | Using multiple variables, the reference types can refer to a memory location. If the variable changes the data in the memory location, the other variable automatically reflects this change in value. Built-in reference example types are: **object**, **dynamic**, | ||
+ | |||
+ | ==Object Type== | ||
+ | |||
+ | The Object Type is an alias for the System.Object class. It is the ultimate base class for all data types in C# Common Type System (CTS). The object types can be assigned with values of any other types, value types, reference types, predefined or user-defined types. Before assigning values, the type conversion is needed. | ||
+ | |||
+ | When a value type is converted to an object type, it is called **boxing** and when an object type is converted to a value type, it is called **unboxing**. | ||
+ | <code C> | ||
+ | object obj; | ||
+ | obj = 100; //This is boxing | ||
+ | </ | ||
+ | |||
+ | ==Dynamic Type== | ||
+ | The data type variable can store any value. But this type checking takes place at run-time. | ||
+ | |||
+ | Syntax for declaring a dynamic type is: | ||
+ | <code C> | ||
+ | dynamic < | ||
+ | </ | ||
+ | For example, | ||
+ | <code C> | ||
+ | dynamic d = 20; | ||
+ | </ | ||
+ | Dynamic types are similar to object types. That type checking for object type variables takes place at compile time. For the dynamic type variables checking takes place at run time. | ||
+ | |||
+ | ==String Type== | ||
+ | The string type allows assigning any string values to a variable. The string type is an alias for the System.String class and is derived from object type. The string type value can be assigned using string literals in two forms: **quoted** and **@quoted**. | ||
+ | |||
+ | For example, | ||
+ | <code C> | ||
+ | string str = " | ||
+ | </ | ||
+ | A @quoted string literal looks as follows: | ||
+ | <code C> | ||
+ | @" | ||
+ | </ | ||
+ | The user-defined reference types are: class, interface, or delegate. | ||
+ | |||
+ | ==Pointer Type== | ||
+ | Pointer type variables store the memory address, which is another type. Pointers in C# are similar to pointers in C or C++. | ||
+ | |||
+ | Syntax for declaring a pointer type is: | ||
+ | <code C> | ||
+ | type* identifier; | ||
+ | </ | ||
+ | For example, | ||
+ | <code C#> | ||
+ | char* cptr; | ||
+ | int* iptr; | ||
+ | </ | ||
+ | |||
+ | |||
+ | ===C# Variables=== | ||
+ | Each variable in C# has a specific type, which determines the size and layout of the variable' | ||
+ | |||
+ | The basic value types in C# can be categorised as follows: | ||
+ | <table C# Variables/ | ||
+ | < | ||
+ | ^ Type ^ Example ^ | ||
+ | | Integral types |sbyte, byte, short, ushort, int, uint, long, ulong, and char | | ||
+ | | Floating point types | float and double | | ||
+ | | Decimal types | decimal | | ||
+ | | Boolean types |true or false values, as assigned | | ||
+ | | Nullable types | Nullable data types | | ||
+ | </ | ||
+ | |||
+ | ==Variable Definitions== | ||
+ | Variable syntax definition in C# is: | ||
+ | < | ||
+ | < | ||
+ | </ | ||
+ | // | ||
+ | |||
+ | Examples of valid variable definitions are shown below: | ||
+ | <code C> | ||
+ | int i, j, k; | ||
+ | char c, ch; | ||
+ | float f, salary; | ||
+ | double d; | ||
+ | </ | ||
+ | |||
+ | Variable can be initialized immediately during definition time: | ||
+ | <code C> | ||
+ | int i = 100; | ||
+ | </ | ||
+ | |||
+ | |||
+ | ==Variables Initialization== | ||
+ | Variables are initialized with an equal sign followed by a constant expression. The general initialization form looks: | ||
+ | <code C> | ||
+ | variable_name = value; | ||
+ | </ | ||
+ | Variables can be initialized during their declaration. The initializer consists of an equal sign followed by a constant expression as: | ||
+ | <code C> | ||
+ | < | ||
+ | </ | ||
+ | Some examples are: | ||
+ | <code C> | ||
+ | int d = 3, f = 5; /* Initializing d and f */ | ||
+ | byte z = 22; /* Initializes z */ | ||
+ | double pi = 3.14159; /* Declares an approximation of PI */ | ||
+ | char x = ' | ||
+ | </ | ||
+ | It is important to initialize variables properly, otherwise sometimes it may produce unexpected result. | ||
+ | |||
+ | The following example uses various types of variables: | ||
+ | <code C> | ||
+ | using System; | ||
+ | |||
+ | namespace VariableDefinition { | ||
+ | class Program { | ||
+ | | ||
+ | short a; | ||
+ | int b ; | ||
+ | | ||
+ | /* Actual initialization */ | ||
+ | a = 10; | ||
+ | b = 20; | ||
+ | c = a + b; | ||
+ | | ||
+ | | ||
+ | } | ||
+ | } | ||
+ | } | ||
+ | </ | ||
+ | |||
+ | Output: | ||
+ | < | ||
+ | a = 10, b = 20, c = 30 | ||
+ | </ | ||
+ | |||
+ | |||
+ | === === | ||
+ | <box # | ||
+ | <box # | ||
+ | ===C# Looping=== | ||
+ | <box # | ||
+ | <box # | ||
+ | |||
+ | C# ((https:// | ||
+ | |||
+ | <table C# Loops/O> | ||
+ | < | ||
+ | ^ Sr.No. ^ Loop Type & Description ^ | ||
+ | | 1 | //while// loop -- it repeats a statement or a group of statements while a given condition is true. It tests the condition before executing the loop body | | ||
+ | | 2 | //for// loop -- it executes a sequence of statements multiple times and abbreviates the code that manages the loop variable | | ||
+ | | 3 | // | ||
+ | | 4 | Nested loop -- you can use one or more loop inside any another //while//, //for// or // | ||
+ | </ | ||
+ | |||
+ | ==while Loop== | ||
+ | A //while// loop statement in C# repeatedly executes a target statement as long as a given condition is true. | ||
+ | < | ||
+ | while(condition) { | ||
+ | | ||
+ | } | ||
+ | </ | ||
+ | |||
+ | Example: | ||
+ | <code C> | ||
+ | using System; | ||
+ | |||
+ | namespace Loops { | ||
+ | class Program { | ||
+ | static void Main(string[] args) { | ||
+ | /* Local variable definition */ | ||
+ | int a = 10; | ||
+ | |||
+ | /* while loop execution */ | ||
+ | while (a < 20) { | ||
+ | Console.WriteLine(" | ||
+ | a++; | ||
+ | } | ||
+ | Console.ReadLine(); | ||
+ | } | ||
+ | } | ||
+ | } | ||
+ | </ | ||
+ | |||
+ | Output: | ||
+ | < | ||
+ | value of a: 10 | ||
+ | value of a: 11 | ||
+ | value of a: 12 | ||
+ | value of a: 13 | ||
+ | value of a: 14 | ||
+ | value of a: 15 | ||
+ | value of a: 16 | ||
+ | value of a: 17 | ||
+ | value of a: 18 | ||
+ | value of a: 19 | ||
+ | </ | ||
+ | |||
+ | ==for Loop== | ||
+ | A //for// loop is a repetition control structure that allows you to efficiently write a loop that needs to execute a specific number of times. | ||
+ | The syntax of a for loop in C# is: | ||
+ | < | ||
+ | for ( init; condition; increment ) { | ||
+ | statement(s); | ||
+ | } | ||
+ | </ | ||
+ | |||
+ | Here is the flow of control in a //for// loop. | ||
+ | |||
+ | - The //init// step is executed first, and only once. This step allows you to declare and initialise any loop control variables. You are not required to put a statement here, as long as a semicolon appears. | ||
+ | - Next, the condition is evaluated. If it is true, the body of the loop is executed. If it is false, the body of the loop does not run, and flow of control jumps to the next statement just after the //for// loop. | ||
+ | - After the body of the //for// loop executes, the flow of control jumps back up to the increment statement. This statement allows you to update any loop control variables. This statement can be left blank, as long as a semicolon appears after the condition. | ||
+ | - The condition is now evaluated again. If it is true, the loop executes, and the process repeats itself (body of the loop, then increment step, and then again testing for a condition). After the condition becomes false, the //for// loop terminates. | ||
+ | |||
+ | Example: | ||
+ | <code C> | ||
+ | using System; | ||
+ | namespace Loops { | ||
+ | class Program { | ||
+ | static void Main(string[] args) { | ||
+ | |||
+ | /* for loop execution */ | ||
+ | for (int a = 10; a < 20; a = a + 1) { | ||
+ | Console.WriteLine(" | ||
+ | } | ||
+ | Console.ReadLine(); | ||
+ | } | ||
+ | } | ||
+ | } | ||
+ | </ | ||
+ | |||
+ | Output: | ||
+ | < | ||
+ | alue of a: 10 | ||
+ | value of a: 11 | ||
+ | value of a: 12 | ||
+ | value of a: 13 | ||
+ | value of a: 14 | ||
+ | value of a: 15 | ||
+ | value of a: 16 | ||
+ | value of a: 17 | ||
+ | value of a: 18 | ||
+ | value of a: 19 | ||
+ | </ | ||
+ | |||
+ | ==The C# do...while Loop== | ||
+ | The syntax of a // | ||
+ | < | ||
+ | do { | ||
+ | statement(s); | ||
+ | } while( condition ); | ||
+ | </ | ||
+ | Notice that the conditional expression appears at the end of the loop, so the statement(s) in the loop execute once before the condition is tested. | ||
+ | |||
+ | If the condition is true, the flow of control jumps back up to //do//, and the statement(s) in the loop execute again. This process repeats until the given condition becomes false. | ||
+ | Example: | ||
+ | <code C> | ||
+ | using System; | ||
+ | |||
+ | namespace Loops { | ||
+ | class Program { | ||
+ | static void Main(string[] args) { | ||
+ | /* Local variable definition */ | ||
+ | int a = 10; | ||
+ | |||
+ | /* do loop execution */ | ||
+ | do { | ||
+ | Console.WriteLine(" | ||
+ | a = a + 1; | ||
+ | } | ||
+ | while (a < 20); | ||
+ | Console.ReadLine(); | ||
+ | } | ||
+ | } | ||
+ | } | ||
+ | </ | ||
+ | |||
+ | Output: | ||
+ | < | ||
+ | value of a: 10 | ||
+ | value of a: 11 | ||
+ | value of a: 12 | ||
+ | value of a: 13 | ||
+ | value of a: 14 | ||
+ | value of a: 15 | ||
+ | value of a: 16 | ||
+ | value of a: 17 | ||
+ | value of a: 18 | ||
+ | value of a: 19 | ||
+ | </ | ||
+ | |||
+ | ==C# Nested for Loop== | ||
+ | C# allows using one loop inside another loop (loop nesting). The following section shows a few examples to illustrate the concept. | ||
+ | The syntax for a nested //for// loop statement in C# is as follows: | ||
+ | < | ||
+ | for ( init; condition; increment ) { | ||
+ | for ( init; condition; increment ) { | ||
+ | statement(s); | ||
+ | } | ||
+ | statement(s); | ||
+ | } | ||
+ | </ | ||
+ | The syntax for a **nested //while// loop** statement in C# is as follows: | ||
+ | < | ||
+ | while(condition) { | ||
+ | while(condition) { | ||
+ | statement(s); | ||
+ | } | ||
+ | statement(s); | ||
+ | } | ||
+ | </ | ||
+ | The syntax for a **nested // | ||
+ | < | ||
+ | do { | ||
+ | statement(s); | ||
+ | do { | ||
+ | statement(s); | ||
+ | } | ||
+ | while( condition ); | ||
+ | } | ||
+ | while( condition ); | ||
+ | </ | ||
+ | |||
+ | A final note on loop nesting is that you can put any type of loop inside of any other type of loop. For example, a for loop can be inside a while loop or vice versa. | ||
+ | Example: | ||
+ | <code C> | ||
+ | using System; | ||
+ | |||
+ | namespace Loops { | ||
+ | class Program { | ||
+ | static void Main(string[] args) { | ||
+ | /* local variable definition */ | ||
+ | int i, j; | ||
+ | |||
+ | for (i = 2; i < 100; i++) { | ||
+ | for (j = 2; j <= (i / j); j++) | ||
+ | if ((i % j) == 0) break; // if factor found, not prime | ||
+ | if (j > (i / j)) Console.WriteLine(" | ||
+ | } | ||
+ | Console.ReadLine(); | ||
+ | } | ||
+ | } | ||
+ | } | ||
+ | </ | ||
+ | |||
+ | Output: | ||
+ | < | ||
+ | 2 is prime | ||
+ | 3 is prime | ||
+ | 5 is prime | ||
+ | 7 is prime | ||
+ | 11 is prime | ||
+ | 13 is prime | ||
+ | 17 is prime | ||
+ | 19 is prime | ||
+ | 23 is prime | ||
+ | 29 is prime | ||
+ | 31 is prime | ||
+ | 37 is prime | ||
+ | 41 is prime | ||
+ | 43 is prime | ||
+ | 47 is prime | ||
+ | 53 is prime | ||
+ | 59 is prime | ||
+ | 61 is prime | ||
+ | 67 is prime | ||
+ | 71 is prime | ||
+ | 73 is prime | ||
+ | 79 is prime | ||
+ | 83 is prime | ||
+ | 89 is prime | ||
+ | 97 is prime | ||
+ | </ | ||
+ | |||
+ | ==Infinite Loop== | ||
+ | A loop becomes infinite loop if a condition never becomes false. The for loop is traditionally used for this purpose. Since none of the three expressions that form the for loop is required, you can make an endless loop by leaving the conditional expression empty. | ||
+ | |||
+ | Example: | ||
+ | <code C> | ||
+ | using System; | ||
+ | |||
+ | namespace Loops { | ||
+ | class Program { | ||
+ | static void Main(string[] args) { | ||
+ | for (; ; ) { | ||
+ | Console.WriteLine(" | ||
+ | } | ||
+ | } | ||
+ | } | ||
+ | } | ||
+ | </ | ||
+ | |||
+ | When the conditional expression is absent, it is assumed to be true. | ||
+ | |||
+ | === === | ||
+ | <box # | ||
+ | <box # | ||
+ | ===C# Program Control Structures=== | ||
+ | <box # | ||
+ | <box # | ||
+ | |||
+ | C# ((https:// | ||
+ | |||
+ | C# provides following types of decision making statements: | ||
+ | \\ | ||
+ | \\ | ||
+ | \\ | ||
+ | \\ | ||
+ | \\ | ||
+ | <table C# Loops/O> | ||
+ | < | ||
+ | ^ Sr.No. ^ Loop Type & Description ^ | ||
+ | | 1 | An //if// statement consists of a boolean expression followed by one or more statements | | ||
+ | | 2 | // | ||
+ | | 3 | Nested //if// statements -- you can use one //if// or //else if// statement inside another //if// or //else if// statement(s) | | ||
+ | | 4 | //switch// statement -- a switch statement allows a variable to be tested for equality against a list of values | | ||
+ | | 5 | Nested //switch// statements -- you can use one switch statement inside another switch statement(s) | | ||
+ | | 6 | The ? Operator | | ||
+ | </ | ||
+ | |||
+ | ==if Statement== | ||
+ | An //if// statement consists of a boolean expression followed by one or more statements. | ||
+ | The syntax of an //if// statement in C# is: | ||
+ | < | ||
+ | if(boolean_expression) { | ||
+ | /* Statement(s) will execute if the boolean expression is true */ | ||
+ | } | ||
+ | </ | ||
+ | |||
+ | If the boolean expression evaluates to true, then the block of code inside the //if// statement is executed. If the boolean expression evaluates to false, then the first set of code after the end of the //if// statement (after the closing curly brace) is executed. | ||
+ | |||
+ | Example: | ||
+ | <code C> | ||
+ | using System; | ||
+ | |||
+ | namespace DecisionMaking { | ||
+ | class Program { | ||
+ | static void Main(string[] args) { | ||
+ | /* Local variable definition */ | ||
+ | int a = 10; | ||
+ | |||
+ | /* Check the boolean condition using if statement */ | ||
+ | if (a < 20) { | ||
+ | /* If condition is true then print the following */ | ||
+ | Console.WriteLine(" | ||
+ | } | ||
+ | Console.WriteLine(" | ||
+ | Console.ReadLine(); | ||
+ | } | ||
+ | } | ||
+ | } | ||
+ | </ | ||
+ | |||
+ | Output: | ||
+ | < | ||
+ | a is less than 20; | ||
+ | value of a is : 10 | ||
+ | </ | ||
+ | |||
+ | ==if...else Statement== | ||
+ | An //if// statement can be followed by an optional //else// statement, which executes when the boolean expression is false. | ||
+ | The syntax of an // | ||
+ | <code C> | ||
+ | if(boolean_expression) { | ||
+ | /* Statement(s) will execute if the boolean expression is true */ | ||
+ | } else { | ||
+ | /* Statement(s) will execute if the boolean expression is false */ | ||
+ | } | ||
+ | </ | ||
+ | If the boolean expression evaluates to true, then the if block of code is executed, otherwise //else// block of code is executed. | ||
+ | |||
+ | Example: | ||
+ | <code C> | ||
+ | using System; | ||
+ | |||
+ | namespace DecisionMaking { | ||
+ | class Program { | ||
+ | static void Main(string[] args) { | ||
+ | /* Local variable definition */ | ||
+ | int a = 100; | ||
+ | |||
+ | /* Check the boolean condition */ | ||
+ | if (a < 20) { | ||
+ | /* If condition is true then print the following */ | ||
+ | Console.WriteLine(" | ||
+ | } else { | ||
+ | /* If condition is false then print the following */ | ||
+ | Console.WriteLine(" | ||
+ | } | ||
+ | Console.WriteLine(" | ||
+ | Console.ReadLine(); | ||
+ | } | ||
+ | } | ||
+ | } | ||
+ | </ | ||
+ | |||
+ | Output: | ||
+ | < | ||
+ | a is not less than 20; | ||
+ | value of a is : 100 | ||
+ | </ | ||
+ | |||
+ | ==Nested if Statement== | ||
+ | It is always legal in C# to nest // | ||
+ | The syntax for a nested //if// statement is as follows: | ||
+ | <code C> | ||
+ | if( boolean_expression 1) { | ||
+ | /* Executes when the boolean expression 1 is true */ | ||
+ | if(boolean_expression 2) { | ||
+ | /* Executes when the boolean expression 2 is true */ | ||
+ | } | ||
+ | } | ||
+ | </ | ||
+ | |||
+ | Example: | ||
+ | <code C> | ||
+ | using System; | ||
+ | |||
+ | namespace DecisionMaking { | ||
+ | class Program { | ||
+ | static void Main(string[] args) { | ||
+ | //* Local variable definition */ | ||
+ | int a = 100; | ||
+ | int b = 200; | ||
+ | |||
+ | /* Check the boolean condition */ | ||
+ | if (a == 100) { | ||
+ | |||
+ | /* If condition is true then check the following */ | ||
+ | if (b == 200) { | ||
+ | /* If condition is true then print the following */ | ||
+ | Console.WriteLine(" | ||
+ | } | ||
+ | } | ||
+ | Console.WriteLine(" | ||
+ | Console.WriteLine(" | ||
+ | Console.ReadLine(); | ||
+ | } | ||
+ | } | ||
+ | } | ||
+ | </ | ||
+ | |||
+ | Output: | ||
+ | <code C> | ||
+ | Value of a is 100 and b is 200 | ||
+ | Exact value of a is : 100 | ||
+ | Exact value of b is : 200 | ||
+ | </ | ||
+ | |||
+ | ==switch Statement== | ||
+ | A //switch// statement allows a variable to be tested for equality against a list of values. Each value is called a case, and the variable being switched on is checked for each switch case. | ||
+ | |||
+ | The syntax for a //switch// statement in C# is as follows: | ||
+ | < | ||
+ | switch(expression) { | ||
+ | case constant-expression | ||
+ | statement(s); | ||
+ | break; /* Optional */ | ||
+ | case constant-expression | ||
+ | statement(s); | ||
+ | break; /* Optional */ | ||
+ | | ||
+ | /* You can have any number of case statements */ | ||
+ | default : /* Optional */ | ||
+ | statement(s); | ||
+ | } | ||
+ | </ | ||
+ | |||
+ | The following rules apply to a //switch// statement. | ||
+ | |||
+ | - The expression used in a //switch// statement must have an integral or enumerated type or be of a class type in which the class has a single conversion function to an integral or enumerated type. | ||
+ | - You can have any number of case statements within a //switch//. Each case is followed by the value to be compared to and a colon. | ||
+ | - The constant-expression for a case must be the same data type as the variable in the //switch//, and it must be a constant or a literal. | ||
+ | - When the variable being switched on is equal to a case, the statements following that case will execute until a break statement is reached. | ||
+ | - When a break statement is reached, the //switch// terminates, and the flow of control jumps to the next line following the //switch// statement. | ||
+ | - Not every case needs to contain a break. If no break appears, the flow of control will fall through to subsequent cases until a break is reached. | ||
+ | - A //switch// statement can have an optional default case, which must appear at the end of the //switch//. The default case can be used for performing a task when none of the cases is true. No break is needed in the default case. | ||
+ | |||
+ | Example: | ||
+ | <code C> | ||
+ | using System; | ||
+ | |||
+ | namespace DecisionMaking { | ||
+ | class Program { | ||
+ | static void Main(string[] args) { | ||
+ | /* Local variable definition */ | ||
+ | char grade = ' | ||
+ | |||
+ | switch (grade) { | ||
+ | case ' | ||
+ | Console.WriteLine(" | ||
+ | break; | ||
+ | case ' | ||
+ | case ' | ||
+ | Console.WriteLine(" | ||
+ | break; | ||
+ | case ' | ||
+ | Console.WriteLine(" | ||
+ | break; | ||
+ | case ' | ||
+ | Console.WriteLine(" | ||
+ | break; | ||
+ | default: | ||
+ | Console.WriteLine(" | ||
+ | break; | ||
+ | } | ||
+ | Console.WriteLine(" | ||
+ | Console.ReadLine(); | ||
+ | } | ||
+ | } | ||
+ | } | ||
+ | </ | ||
+ | |||
+ | Output: | ||
+ | < | ||
+ | Well done | ||
+ | Your grade is B | ||
+ | </ | ||
+ | |||
+ | |||
+ | ==Nested switch Statement== | ||
+ | It is possible to have a //switch// as part of the statement sequence of an outer //switch//. Even if the case constants of the inner and outer //switch// contain common values, no conflicts will arise. | ||
+ | |||
+ | The syntax for a nested //switch// statement is as follows: | ||
+ | < | ||
+ | switch(ch1) { | ||
+ | case ' | ||
+ | Console.WriteLine(" | ||
+ | |||
+ | switch(ch2) { | ||
+ | case ' | ||
+ | Console.WriteLine(" | ||
+ | break; | ||
+ | case ' | ||
+ | } | ||
+ | break; | ||
+ | case ' | ||
+ | } | ||
+ | |||
+ | Example: | ||
+ | <code C> | ||
+ | using System; | ||
+ | |||
+ | namespace DecisionMaking { | ||
+ | class Program { | ||
+ | static void Main(string[] args) { | ||
+ | int a = 100; | ||
+ | int b = 200; | ||
+ | |||
+ | switch (a) { | ||
+ | case 100: | ||
+ | Console.WriteLine(" | ||
+ | | ||
+ | switch (b) { | ||
+ | case 200: | ||
+ | Console.WriteLine(" | ||
+ | break; | ||
+ | } | ||
+ | break; | ||
+ | } | ||
+ | Console.WriteLine(" | ||
+ | Console.WriteLine(" | ||
+ | Console.ReadLine(); | ||
+ | } | ||
+ | } | ||
+ | } | ||
+ | </ | ||
+ | |||
+ | Output: | ||
+ | < | ||
+ | This is part of outer switch | ||
+ | This is part of inner switch | ||
+ | Exact value of a is : 100 | ||
+ | Exact value of b is : 200 | ||
+ | </ | ||
+ | |||
+ | |||
+ | === === | ||
+ | <box # | ||
+ | <box # | ||
+ | ===C# Classes=== | ||
+ | <box # | ||
+ | <box # | ||
+ | |||
+ | ==Defining a Class== | ||
+ | A C# ((https:// | ||
+ | <code c> | ||
+ | <access specifier> | ||
+ | //Member variables | ||
+ | <access specifier> | ||
+ | <access specifier> | ||
+ | ... | ||
+ | <access specifier> | ||
+ | //Member methods | ||
+ | <access specifier> | ||
+ | //Method body | ||
+ | } | ||
+ | <access specifier> | ||
+ | //Method body | ||
+ | } | ||
+ | ... | ||
+ | <access specifier> | ||
+ | //Method body | ||
+ | } | ||
+ | } | ||
+ | </ | ||
+ | Note: | ||
+ | * access specifiers specify the access rules for the members as well as the class itself. If not mentioned, then the default access specifier for a class type is internal. Default access for the members is private; | ||
+ | * data type specifies the type of variable, and return type specifies the data type of the data the method returns if any; | ||
+ | * to access the class members, you use the dot (.) operator; | ||
+ | * the dot operator links the name of an object with the name of a member. | ||
+ | |||
+ | Example: | ||
+ | <code c> | ||
+ | using System; | ||
+ | |||
+ | namespace BoxApplication { | ||
+ | |||
+ | class Box { | ||
+ | public double length; | ||
+ | public double breadth; | ||
+ | public double height; | ||
+ | } | ||
+ | class Boxtester { | ||
+ | static void Main(string[] args) { | ||
+ | Box Box1 = new Box(); | ||
+ | Box Box2 = new Box(); | ||
+ | double volume = 0.0; //Store the volume of a box here | ||
+ | |||
+ | //Box1 specification | ||
+ | Box1.height = 5.0; | ||
+ | Box1.length = 6.0; | ||
+ | Box1.breadth = 7.0; | ||
+ | |||
+ | //Box2 specification | ||
+ | Box2.height = 10.0; | ||
+ | Box2.length = 12.0; | ||
+ | Box2.breadth = 13.0; | ||
+ | | ||
+ | //Volume of Box1 | ||
+ | volume = Box1.height * Box1.length * Box1.breadth; | ||
+ | Console.WriteLine(" | ||
+ | |||
+ | //Volume of Box2 | ||
+ | volume = Box2.height * Box2.length * Box2.breadth; | ||
+ | Console.WriteLine(" | ||
+ | Console.ReadKey(); | ||
+ | } | ||
+ | } | ||
+ | } | ||
+ | </ | ||
+ | |||
+ | |||
+ | Output: | ||
+ | <code C> | ||
+ | Volume of Box1 : 210 | ||
+ | Volume of Box2 : 1560 | ||
+ | </ | ||
+ | |||
+ | ==Member Functions and Encapsulation== | ||
+ | A member function of a class is a function that has its definition or its prototype within the class definition similar to any other variable. It operates on an object of the class of which it is a member, and has access to all the members of a class for that object. | ||
+ | |||
+ | Member variables are the attributes of an object (from the design perspective), | ||
+ | |||
+ | Sample: | ||
+ | <code c> | ||
+ | using System; | ||
+ | |||
+ | namespace BoxApplication { | ||
+ | class Box { | ||
+ | private double length; | ||
+ | private double breadth; | ||
+ | private double height; | ||
+ | | ||
+ | public void setLength( double len ) { | ||
+ | | ||
+ | } | ||
+ | public void setBreadth( double bre ) { | ||
+ | | ||
+ | } | ||
+ | public void setHeight( double hei ) { | ||
+ | | ||
+ | } | ||
+ | public double getVolume() { | ||
+ | | ||
+ | } | ||
+ | } | ||
+ | class Boxtester { | ||
+ | static void Main(string[] args) { | ||
+ | Box Box1 = new Box(); | ||
+ | Box Box2 = new Box(); | ||
+ | | ||
+ | |||
+ | // | ||
+ | // | ||
+ | | ||
+ | | ||
+ | | ||
+ | |||
+ | // | ||
+ | | ||
+ | | ||
+ | | ||
+ | |||
+ | // | ||
+ | | ||
+ | | ||
+ | |||
+ | // | ||
+ | | ||
+ | | ||
+ | |||
+ | | ||
+ | } | ||
+ | } | ||
+ | } | ||
+ | </ | ||
+ | |||
+ | Output: | ||
+ | < | ||
+ | Volume of Box1 : 210 | ||
+ | Volume of Box2 : 1560 | ||
+ | </ | ||
+ | |||
+ | ==C# Constructors== | ||
+ | A class constructor is a special member function of a class that is executed whenever we create new objects of that class. | ||
+ | |||
+ | A constructor has the same name as that of class, and it does not have any return type. | ||
+ | |||
+ | Example: | ||
+ | <code C> | ||
+ | using System; | ||
+ | |||
+ | namespace LineApplication { | ||
+ | class Line { | ||
+ | private double length; | ||
+ | | ||
+ | public Line() { | ||
+ | | ||
+ | } | ||
+ | public void setLength( double len ) { | ||
+ | | ||
+ | } | ||
+ | public double getLength() { | ||
+ | | ||
+ | } | ||
+ | |||
+ | static void Main(string[] args) { | ||
+ | Line line = new Line(); | ||
+ | |||
+ | //Set line length | ||
+ | | ||
+ | | ||
+ | | ||
+ | } | ||
+ | } | ||
+ | } | ||
+ | </ | ||
+ | |||
+ | Output: | ||
+ | < | ||
+ | Object is being created | ||
+ | Length of line : 6 | ||
+ | </ | ||
+ | |||
+ | A default constructor does not have any parameter, but you can make one if you need to pass some setup values on the initialisation -- such constructors are called parameterised constructors. This technique helps you to assign an initial value to an object at the time of its creation. | ||
+ | |||
+ | Example: | ||
+ | <code C> | ||
+ | using System; | ||
+ | |||
+ | namespace LineApplication { | ||
+ | class Line { | ||
+ | private double length; | ||
+ | | ||
+ | public Line(double len) { // | ||
+ | | ||
+ | | ||
+ | } | ||
+ | public void setLength( double len ) { | ||
+ | | ||
+ | } | ||
+ | public double getLength() { | ||
+ | | ||
+ | } | ||
+ | static void Main(string[] args) { | ||
+ | Line line = new Line(10.0); | ||
+ | | ||
+ | |||
+ | //Set line length | ||
+ | | ||
+ | | ||
+ | | ||
+ | } | ||
+ | } | ||
+ | } | ||
+ | </ | ||
+ | |||
+ | Output: | ||
+ | < | ||
+ | Object is being created, length = 10 | ||
+ | Length of line : 10 | ||
+ | Length of line : 6 | ||
+ | </ | ||
+ | |||
+ | ==C# Destructors== | ||
+ | A destructor is a special member function of a class that is executed whenever an object of its class goes out of scope. A destructor has the same name as that of the class with a prefixed tilde (~), and it can neither return a value nor can it take any parameters. | ||
+ | C# (.NET environment) has a built-in memory management system that tracks unused objects and release memory automatically, | ||
+ | Destructors cannot be inherited or overloaded. | ||
+ | |||
+ | Example: | ||
+ | <code C> | ||
+ | using System; | ||
+ | |||
+ | namespace LineApplication { | ||
+ | class Line { | ||
+ | private double length; | ||
+ | | ||
+ | public Line() { // | ||
+ | | ||
+ | } | ||
+ | ~Line() { // | ||
+ | | ||
+ | } | ||
+ | public void setLength( double len ) { | ||
+ | | ||
+ | } | ||
+ | public double getLength() { | ||
+ | | ||
+ | } | ||
+ | static void Main(string[] args) { | ||
+ | Line line = new Line(); | ||
+ | |||
+ | //Set line length | ||
+ | | ||
+ | | ||
+ | } | ||
+ | } | ||
+ | } | ||
+ | </ | ||
+ | |||
+ | |||
+ | Output: | ||
+ | < | ||
+ | Object is being created | ||
+ | Length of line : 6 | ||
+ | Object is being deleted | ||
+ | </ | ||
+ | |||
+ | |||
+ | ==Static Members of a C# Class== | ||
+ | We can define class members as static using the static keyword. When we declare a member of a class as static, it means no matter how many objects of the class are created, there is only one copy of the static member. | ||
+ | |||
+ | The keyword static implies that only one instance of the member exists for a class. Static variables are used for defining constants because their values can be retrieved by invoking the class without creating an instance of it. Static variables can be initialised outside the member function or class definition. You can also initialise static variables inside the class definition. | ||
+ | |||
+ | Example: | ||
+ | <code C> | ||
+ | using System; | ||
+ | |||
+ | namespace StaticVarApplication { | ||
+ | class StaticVar { | ||
+ | public static int num; | ||
+ | | ||
+ | public void count() { | ||
+ | | ||
+ | } | ||
+ | public int getNum() { | ||
+ | | ||
+ | } | ||
+ | } | ||
+ | class StaticTester { | ||
+ | static void Main(string[] args) { | ||
+ | | ||
+ | | ||
+ | |||
+ | | ||
+ | | ||
+ | | ||
+ | |||
+ | | ||
+ | | ||
+ | | ||
+ | |||
+ | | ||
+ | | ||
+ | | ||
+ | } | ||
+ | } | ||
+ | } | ||
+ | </ | ||
+ | |||
+ | Output: | ||
+ | < | ||
+ | Variable num for s1: 6 | ||
+ | Variable num for s2: 6 | ||
+ | </ | ||
+ | |||
+ | You can also declare a member function as static. Such functions can access only static variables. The static functions exist even before the object is created. | ||
+ | Example: | ||
+ | <code C> | ||
+ | using System; | ||
+ | |||
+ | namespace StaticVarApplication { | ||
+ | class StaticVar { | ||
+ | public static int num; | ||
+ | | ||
+ | public void count() { | ||
+ | | ||
+ | } | ||
+ | public static int getNum() { | ||
+ | | ||
+ | } | ||
+ | } | ||
+ | class StaticTester { | ||
+ | static void Main(string[] args) { | ||
+ | | ||
+ | |||
+ | | ||
+ | | ||
+ | | ||
+ | |||
+ | | ||
+ | | ||
+ | } | ||
+ | } | ||
+ | } | ||
+ | </ | ||
+ | |||
+ | Output: | ||
+ | < | ||
+ | Variable num: 3 | ||
+ | </ | ||
+ | |||
+ | |||
+ | ===C# Events=== | ||
+ | Events occur when a user makes actions like a key press, clicks, mouse movements, etc., or some other occurrence such as system-generated notifications. Applications must respond to events if they occur, i.e. handle interrupts. Events are used during inter-process communication. | ||
+ | |||
+ | ==Using Delegates With Events== | ||
+ | The events are declared and raised in a class. They are associated with the event handlers using delegates within the same class or some other class. To publish the event, the class containing it must be defined. It is called the **publisher** class. Some other class that accepts this event is called the **subscriber** class. Events use the **publisher-subscriber** model. | ||
+ | |||
+ | The object containing a definition of the event and the delegate is named **publisher**. The event-delegate association is also defined in this object. A publisher class object invokes the event, and it is notified to other objects. | ||
+ | |||
+ | A **subscriber** is an object that accepts the event and provides an event handler. The delegate in the publisher class invokes the method (event handler) of the subscriber class. | ||
+ | |||
+ | ==Declaring Events== | ||
+ | To declare an event inside a class, first, a delegate type for the event must be declared. For example, | ||
+ | <code C> | ||
+ | public delegate string MyDel(string str); | ||
+ | </ | ||
+ | Next, the event itself is declared, using the event keyword: | ||
+ | <code C> | ||
+ | event MyDel MyEvent; | ||
+ | </ | ||
+ | The preceding code defines a delegate named " | ||
+ | |||
+ | Example: | ||
+ | <code C> | ||
+ | using System; | ||
+ | |||
+ | namespace SampleApp { | ||
+ | | ||
+ | |||
+ | class EventProgram { | ||
+ | event MyDel MyEvent; | ||
+ | |||
+ | public EventProgram() { | ||
+ | | ||
+ | } | ||
+ | public string WelcomeUser(string username) { | ||
+ | | ||
+ | } | ||
+ | static void Main(string[] args) { | ||
+ | | ||
+ | | ||
+ | | ||
+ | } | ||
+ | } | ||
+ | } | ||
+ | </ | ||
+ | |||
+ | Output: | ||
+ | < | ||
+ | Welcome Tutorials Point | ||
+ | </ | ||
+ | |||
+ | |||
+ | |||
+ | |||
+ | |||
+ | |||
+ | |||
+ | |||
+ | ====== | ||
+ | <box # | ||
+ | <box # | ||
+ | ====== Introduction to the IoT Communication and Networking ====== | ||
+ | <box # | ||
+ | <box # | ||
+ | |||
+ | < | ||
+ | In no doubt, IoT is network oriented – even the name IoT naturally relates to the Internet network. Communication is an essential part of IoT idea. Every IoT device must communicate somehow, even most simple, passive RFID tag – it responds with some data to the excitation. | ||
+ | Communication is always performed with some rules known for both communicating parties. Like people have their different languages to use, devices have protocols. Communication protocol describes how to address the information to the remote device, how to encode the data, how to check the correctness of the incoming message. The physical layer of protocol description also tells how to transmit every bit of data, what is the frequency of radio waves, how fast we can send the data, what is the maximum range of the transmission. | ||
+ | |||
+ | Communication in IoT devices can be wired or wireless. | ||
+ | |||
+ | IoT networking is much different than typical, multilayered, | ||
+ | |||
+ | Indeed constrained IoT devices are usually unable to operate regular – full time on, ISO/OSI layered stack, because of constrained resources. In details it primary means, IoT devices are limited by the processor power, RAM and storage sizes and mainly because of limited power resources. IoT device is expected to be energy efficient, thus low powered, that in most cases excludes typical wireless connection standards, e.g. WiFi. On the other hand, IoT devices are expected to communicate over long distances – some couple or a dozen of kilometres – where wired infrastructure like Ethernet cables and related infrastructure is non-existent and most of the wired technologies, | ||
+ | |||
+ | Also, IoT devices daily life-cycle is much different than, e.g. or PC life-cycle. We as humans used to switch on the notebook, work extensively on the web, then put it to the low power or off, making the machine to sleep, hibernate or just shutting it down. And we wake it up when needed. It barely makes network operation during sleep. IoT devices are expected to be sleeping providing low power mode whenever possible, and on the other hand, they' | ||
+ | |||
+ | Because of the existence of different IoT devices including those very constrained from 8-bit processors with some kB of the RAM to 32-bit multicore machines well-replacing PCs, IoT networking is very competitive on protocols, approaches and solutions. There are indeed some networking standards introduced by standardisation organisation like IEEE, yet they are competed by large manufacturers forcing their complex solutions including dedicated hardware, software and protocols. The third force driving this market are open solutions and enthusiasts, | ||
+ | |||
+ | Following chapters explain some most popular concepts about how to organise network fulfilling the above constraints on communication between IoT devices (Machine-2-Machine) and how to let them communicate with the Internet: including hardware, software and human-users. We focus on the de-facto standards existing in the web, usually as open-source libraries and somewhat low-cost devices. | ||
+ | |||
+ | An interesting survey made by RS components ((11 Internet of Things (IoT) Protocols You Need to Know About, DesignSpark, | ||
+ | |||
+ | * "5.1. [[en: | ||
+ | |||
+ | * "5.2. [[en: | ||
+ | |||
+ | * "5.3. [[en: | ||
+ | |||
+ | * "5.4. [[en: | ||
+ | |||
+ | * "5.5. [[en: | ||
+ | ===== ===== | ||
+ | <box # | ||
+ | <box # | ||
+ | ===== Networking Overview ===== | ||
+ | <box # | ||
+ | <box # | ||
+ | |||
+ | IoT devices are not separated from the global networking environment that nowadays is highly integrated, connecting various wired and wireless transmission standards into one network called the Internet. Indeed some networks are separated because of security and safety reasons and regulations, | ||
+ | |||
+ | XXI century brought wide acceptance of wireless connections. They became very popular even in so-called pico-networks, | ||
+ | |||
+ | |||
+ | The similar way to the regular Internet networking, IoT networking is implemented using (usually simplified) layered stack, similar to the regular ISO/OSI 7 layer networking stack well known to all IT students ((https:// | ||
+ | <figure networking-ISO-OSI> | ||
+ | {{ : | ||
+ | < | ||
+ | </ | ||
+ | Level 1 is a Physical Layer (PHY). On top of it, there is level 2 is Data Link Layer with Media Access Control and Logical Link Control (MAC/ | ||
+ | |||
+ | A quick overview of popular communication technologies for the Internet is presented in Figure {{ref> | ||
+ | |||
+ | Another factor is the communication bandwidth. Fortunately, | ||
+ | |||
+ | <figure networking-wireless-poster> | ||
+ | {{ : | ||
+ | < | ||
+ | </ | ||
+ | |||
+ | In many cases, IoT remote, distant nodes do not need constant communication, | ||
+ | In such case, IoT devices utilize differently, | ||
+ | <figure IoTStack> | ||
+ | {{ : | ||
+ | < | ||
+ | </ | ||
+ | ===== ===== | ||
+ | <box # | ||
+ | <box # | ||
+ | ===== Communication Models ===== | ||
+ | <box # | ||
+ | <box # | ||
+ | |||
+ | IoT Devices can be classified regarding their ability to implement full protocol stacks of the typical, Internet protocols like IPv4, IPv6, HTTP, etc. | ||
+ | * Devices unable to implement full, protocol stack without external support, like, i.e. Arduino Uno (R3) with 32 kb of the flash memory, 16 MHz single core processor and 2 kB of static ram, battery powered, consuming some couple of mW while operating. | ||
+ | * Devices able to implement full, protocol stack yet still limited by their resources, i.e. ESP8266 and ESP32 chips, battery powered, consuming some dozen or hundred of mW while operating. | ||
+ | * Devices that do can offer various, advanced network services, capable of implementing protocol stack with ease yet not servers, routers or gateways, i.e. Raspberry Pi and its clones. Usually, DC powered with power consumption far above 1–2 W, usually up to 10–15 W. | ||
+ | * Dedicated solutions for gateways, routers, usually with embedded, hardware-based implementations of the switching logic, utilising some 10-50W of power. | ||
+ | * Universal IoT computers (i.e. Intel IoT), using PC-grade processors (x86, but sometime ARM), using some about up to 100 W of power. | ||
+ | |||
+ | Some IoT networks are also constrained by the number of IP addresses available regarding the number of IoT devices ones need to connect, so their topology is //a priori// prepared as NAT (Network Adress Translation) solution ((RFC 1631: http:// | ||
+ | |||
+ | IoT devices are usually expected to deliver their data to some cloud for storage and processing while the cloud can send back commands to the actuators/ | ||
+ | |||
+ | Finally, there are security concerns, which make the IoT devices to be put in some separate sub-network and guarded by the firewall. | ||
+ | |||
+ | All of it brings the three, main communication models, explained below. | ||
+ | ==== Device to Device and Industry 4.0 Revolution ==== | ||
+ | Device to device communication model, sometimes referenced as M2M (Machine to Machine communication model) used to be implemented between the homogeneous class of the IoT devices. Nowadays, there is a need to enable heterogeneous systems to collaborate and talk one to another. In a device to a device model, communication is usually held simple, sometimes with niche, proprietary protocols, i.e. ANT/ANT+ ((https:// | ||
+ | |||
+ | Device to device model is highly utilized in the Industrial Automation Control systems and recently very popular in developing Industry 4.0 (I4.0) solutions, where manufacturing devices, i.e. robots and other Cyber-Physical systems (CPS) communicate to set operation sequence for optimal manufacturing process (so-called Industry 4.0) thus providing elastic working zones along with manufacturing flexibility and self-adaptation of the processes. It happens because of the presence of various IoT devices (here sometimes referenced as Industrial IoT) and advanced data processing including Big and Small data. Such a device to device networks very frequently mimics popular P2P (peer to peer) networks, where one device can virtually contact any other to ask for information or deliver one. Comparing to the classical, tree-like topology, a device to device communication constitutes a graph of relations rather than a hierarchized tree. The Figure {{ref> | ||
+ | |||
+ | <figure device-to-deviceIO40> | ||
+ | {{ : | ||
+ | < | ||
+ | </ | ||
+ | |||
+ | The device to device communication assumes, participating devices are smart enough to talk one another, without the need of the translation nor advanced data processing, even if their nature is different (e.g. your intelligent door can inform your smart, IoT kettle to start boiling water once they get informed about poor weather condition by the Internet weather monitoring service, when you're back home after long day of work). Devices constituting mesh or scatter network communicate virtually one another similar way people do. The Figure {{ref> | ||
+ | <figure device-to-device> | ||
+ | {{ : | ||
+ | < | ||
+ | </ | ||
+ | |||
+ | ==== Device to Gateway ==== | ||
+ | Device to gateway communication occurs when there is a need to provide the translate information between different networks, i.e. some Zigbee ((http:// | ||
+ | |||
+ | Gatewaying and protocol translation can also occur on the 6th and 7th level of the ISO/OSI model when the implementation of high-level protocols overwhelms even more advanced IoT devices, i.e. simple MQTT texting can be converted to the XML, heavy messages or exposed as XHTML. Those solutions are mostly software-based, | ||
+ | |||
+ | <figure device-to-gateway> | ||
+ | {{ : | ||
+ | < | ||
+ | </ | ||
+ | |||
+ | ==== Device to Cloud ==== | ||
+ | As IoT devices are usually unable to constitute an efficient computation structure (as single IoT node or even their federation), | ||
+ | |||
+ | <figure device-to-cloud> | ||
+ | {{ : | ||
+ | < | ||
+ | </ | ||
+ | ===== ===== | ||
+ | <box # | ||
+ | <box # | ||
+ | ===== Media Layers – Wired Networking ===== | ||
+ | <box # | ||
+ | <box # | ||
+ | |||
+ | While the IoT ecosystem is usually considered to be composed of wireless devices, it is still possible to connect IoT solutions using a wired connection. | ||
+ | In this chapter, we do not present communication protocols that are short distant one designed to connect sensors to IoT device, like I2C, SPI, Serial, etc. Those are described in chapter "4.2. Embedded Systems Communication Protocols" | ||
+ | |||
+ | When wireless-enabled SoCs where about to be delivered to the market (i.e. ESP8266), there were already available sorts of extension devices for popular Embedded systems, like i.e. Ethernet Shield for Arduino boards. | ||
+ | <figure net_ethernet_shields> | ||
+ | {{ : | ||
+ | {{ : | ||
+ | < | ||
+ | </ | ||
+ | |||
+ | Cooper based wired networks also bring an extra feature to the IoT designers – an ability to power the device via a wired connection, i.e. PoE (Power over Ethernet) – 802.3af, 802.3at, 802.3bt ((https:// | ||
+ | |||
+ | A non exhaustive list of some present and former wired networking solutions are presented in the Table {{ref> | ||
+ | <table wired_protocols> | ||
+ | < | ||
+ | ^ Name ^ Communication medium ^ Max speed ^ Topology ^ Max range (single segment, passive) ^ | ||
+ | | Ethernet |Twisted pair: 10BaseT\\ Coaxial: 10Base2/ | ||
+ | | Fast Ethernet |Twisted pair: 100BaseTx\\ Fibre: 100BaseFx | ||
+ | | Gigabit Ethernet |Twisted pair: 1000BaseT\\ Fibre: 1000BaseX (LX/ | ||
+ | |Local Talk (Apple) |Twisted pair | 0.23 Mbps |Bus, Star (PhoneNet) | ||
+ | |Token ring |Twisted pair | 16 Mbps | Star wired ring |22.5 m / 100 m (cable dependent) | ||
+ | |FDDI |Fibre | ||
+ | </ | ||
+ | |||
+ | Nowadays, the most popular wired networks are 10/ | ||
+ | ===== ===== | ||
+ | <box # | ||
+ | <box # | ||
+ | ===== Media Layers – Wireless Protocols ====== | ||
+ | <box # | ||
+ | <box # | ||
+ | |||
+ | Wireless connections define core communication for IoT devices. Wast and growing amount of protocols, their variations and dynamic IoT networking market, all present non-solid situation where old " | ||
+ | |||
+ | <figure iot-protocols> | ||
+ | {{ : | ||
+ | < | ||
+ | </ | ||
+ | |||
+ | ==== PHY + MAC + LLC Layers ==== | ||
+ | |||
+ | Below we present currently most popular, wireless protocols review for the lower ISO/OSI layers (1–2, some of them also implement layer 3 – Networking). | ||
+ | |||
+ | === WiFi === | ||
+ | WiFI is the set of standards for wireless communication using the 2.4 GHz or 5 GHz band, slightly different spectrum in different countries. The core specification of the 2.4 GHz contains 14 channels with 20 MHz (currently 40 MHz) bandwidth. While there is no centralised physical layer controller, collisions frequently occur even more with a growing number of devices sharing the band. The collision is handled using CSMA-CA with a random binary exponential increase of repeating time. | ||
+ | |||
+ | With the high speed of transmission and range usually not exceeding 100 m, it is widely used as the direct replacement of wired Ethernet in local area networks. It is a very good choice while the amount of data to be transferred is larger, for example, video streams or assembled IoT stream delivered by gateways. It is also possible to use it in direct connectivity for smart sensors, and other IoT elements, but the protocol itself is not designed to transmit small data packets. For many IoT applications, | ||
+ | <table Ref.Tab.1.1> | ||
+ | < | ||
+ | ^ 802.11 standard ^ Transmission speed ^ Frequency ^ | ||
+ | | 802.11b | 11 Mbps | 2.4 GHz | | ||
+ | | 802.11g | 54 Mbps | 2.4 GHz | | ||
+ | | 802.11n | 150 Mbps | 2.4 GHz | | ||
+ | | | 300 Mbps | 5 GHz | | ||
+ | | 802.11ac | 1 Gbps | 5 GHz | | ||
+ | </ | ||
+ | |||
+ | === Bluetooth === | ||
+ | Bluetooth is a prevalent method of connecting a variety of devices in short distance. Almost every computer and a smartphone have Bluetooth module built-in. Standard has been defined by Bluetooth SIG (Special Interest Group) founded in 1998. Bluetooth operates in the 2.4 GHz band with 79 channels with automatic channel switching when interference occurs (hopping frequency). The single channel offers up to about 1Mbps (where around 700kbps is available for the user) bandwidth, and it provides communication within the range from up to 1 m (class 3, 1 mW) till up to 100 m (class 1, 100 mW). The most popular version is class 2 with 10 m range (2.5 mW). | ||
+ | |||
+ | Every Bluetooth device has a unique, 48-bit MAC address. | ||
+ | |||
+ | Bluetooth offers various " | ||
+ | |||
+ | Now Bluetooth covers two branches: BR/EDR (Basic Rate/ | ||
+ | |||
+ | Classical (prior to BLE and 4.0) Bluetooth networks can create ad-hoc, so-called WPAN (Wireless Personal Area Networks) sometimes referenced as Piconets. Bluetooth Piconet can handle up to 7 + 1 devices, where 1 device acts as Master, and it can contact up to 7 Slave devices. Only the Master device can initiate a connection. Fortunately for the IoT approach, much Bluetooth hardware can act as Slave and Master simultaneously, | ||
+ | |||
+ | <figure net_bt_scatternet> | ||
+ | {{ : | ||
+ | < | ||
+ | </ | ||
+ | |||
+ | Bluetooth Low Energy (BLE) uses an simplified implementation of the state machine thus is more constrained-devices friendly. It offers a limited range, and it is designed to expose the state rather than transmit streamed data. It provides a speed reaching up to about 1.4 Mbps (2 Mbps aerial throughput) if needed, however. It uses 2.4 GHz band but is designed to avoid interference with WiFi AP and clients. Communication is organised into three advertising channels (located " | ||
+ | |||
+ | Latest Bluetooth implementations (protocol version 5.0 and newer, implemented in mid-2017) offer a Bluetooth mesh network extending ubiquitous connectivity via many-to-many communication model, dedicated to IoT devices, lighting, Industry 4.0, etc. The Bluetooth mesh is layer-organised, | ||
+ | \\ | ||
+ | \\ | ||
+ | |||
+ | <figure bt-5-mesh> | ||
+ | {{ : | ||
+ | < | ||
+ | </ | ||
+ | \\ | ||
+ | \\ | ||
+ | \\ | ||
+ | \\ | ||
+ | \\ | ||
+ | \\ | ||
+ | <table Ref.Tab.1.2> | ||
+ | < | ||
+ | ^ Bluetooth ^ Transmission speed ^ Remarks ^ | ||
+ | | 1.0 | 21 kbps | Few implementations | | ||
+ | | 1.1 | 124 kbps | | | ||
+ | | 1.2 | 328 kbps | First popular version | | ||
+ | | 2.0 + EDR | 3 Mbps | Extended Data Rate | | ||
+ | | 3.0 + HS | 24 Mbps | High Speed | | ||
+ | | 3.1 + HS | 40 Mbps | | | ||
+ | | 4.0 + LE | 1 Mbps | Low Energy | | ||
+ | | 4.1 | Designed for IoT | | | ||
+ | | 5.0 | One standard for all purposes | | | ||
+ | </ | ||
+ | |||
+ | === Cellular === | ||
+ | Cellular (mobile/ | ||
+ | |||
+ | Figure {{ref> | ||
+ | |||
+ | <figure gsm_generations> | ||
+ | {{ : | ||
+ | < | ||
+ | </ | ||
+ | |||
+ | Figure {{ref> | ||
+ | |||
+ | <figure gsm-net> | ||
+ | {{ : | ||
+ | {{ : | ||
+ | < | ||
+ | </ | ||
+ | |||
+ | GSM protocols are proprietary, | ||
+ | |||
+ | On the one hand, the GSM network seems to be a good solution for extended distant IoT networks; on the other, they have many disadvantages, | ||
+ | |||
+ | **Important!** Professional operation requires licencing and connecting existing infrastructure involves a purchase of the unique identifier (phone ID and a number that is given by the SIM card, physical or virtual) and a service fee. | ||
+ | |||
+ | By the limited access constraints there do exist one more – GSM boards are using quite a significant amount of energy when establishing a connection because they need to broadcast their existence as far as possible, to gain a connection with a possibly distant-located base station. It requires tremendous power and drains the battery (even up to 10 W peak); thus, cellular solutions are not suitable for the IoT devices that use frequent data communication. | ||
+ | |||
+ | === ZigBee === | ||
+ | ZigBee protocol is so far very popular in Smart House but also in Industry appliances. Zigbee is a wireless technology developed as an open standard to address the needs of low-cost, low-power wireless machine to machine networks. It is more popular in the industry, however, but because of the relatively higher cost of equipment in comparison with WiFi, Bluetooth or other RF modules. The Zigbee standard operates on the radio bands 2.4 GHz for smart home applications, | ||
+ | |||
+ | === Z-Wave === | ||
+ | Z-Wave is a protocol similar in principals to the ZigBee, but hardware is cheaper; thus, it is more towards inexpensive home automation systems. Like in ZigBee, Z-Wave operates on different frequencies depending on the world region, usually between 865 MHz and 926 MHz. Transmission speed is up to 200 kbps, and the range is up to 100m. A single Z-Wave network is pretty limited on a number of concurrent devices in one network, that is only 232 devices. Each Z-Wave network has a unique ID, and each node (device) in a network has a unique 8-bit identifier. | ||
+ | |||
+ | === Thread === | ||
+ | Another standard ((Thread Stack Fundamentals, | ||
+ | |||
+ | === NFC === | ||
+ | NFC (Near Field Communication) is a technology that enables two-way interactions between electronic devices. What is important one of the devices does not have to be equipped with the power source – it is powered by the receiving radio signal. That’s why NFC is used in contactless card technology enabling devices to exchange the data at a distance of less than 4 cm. | ||
+ | Transmission speed varies between 100–420 kbps, range between both active devices is up to 10 cm, operating frequency 13.56 MHz. | ||
+ | |||
+ | === Sigfox === | ||
+ | Sigfox ((https:// | ||
+ | |||
+ | === LoRaWAN === | ||
+ | LoRa (Long Range) is the technology for data transmission with relatively low speed (20 bps do 41 kbps) and the range about 2 km (new transceivers can transmit data up to 15 km). It uses CSS (Chirp Spread Spectrum) modulation in the 433 MHz ISM radio band. The cell topology is the star with the gateway placed at the central point. End-devices use one hop communication with the gateway, that is connected to the standard IP network with a central network server. The LoRa technology is supported as LoRa WAN by LoRa Alliance ((https:// | ||
+ | |||
+ | ==== NET (NWY) Layer ==== | ||
+ | Traditionally, | ||
+ | |||
+ | === IPv4 === | ||
+ | Internet Protocol v4 (1981) is perhaps the most widespread networking protocol. The predecessor of the IPv4 protocol originally called IP was introduced in 1974 and supported up to 2^8 hosts, organised in 2^4 subnetworks (RFC 675). | ||
+ | |||
+ | In IPv4 (RFC 760/RFC791) the logical addressing space was extended to 2^32 devices that seemed to be quote much in 1981, but now we struggle with lack of free addressing space. This number is less because some addresses are reserved, e.g. for broadcasting and due to the existence of different classes of addresses and their pools ((https:// | ||
+ | |||
+ | Some relief to suffocating Internet was brought as an ad-hoc solution with an introduction of the NAT (Network Address Translation). NAT-enabled subnetworks are those, where one public address represents a set of devices hidden behind the router, but that limits usability because of lack of direct access and unique identification in the global network of the devices sharing private address spaces. Even so, there are about 8.5 billion IoT devices expected to be connected to the Internet by the end of the 2017 year, according to the Gartner' | ||
+ | |||
+ | === IPv6 === | ||
+ | IPv6 is the next generation of the IPv4 protocol. It is supposed to replace IPv4, but this process is somehow not so quick as there are many solutions still present on the Internet and Intranets that implement IPv4 only and would become inoperable if IPv4 would not be available anymore. IPv6 brings addressing space large enough to cover all existing and future needs. The number of possible addresses is 2^128. Addresses are presented by 8 groups of 4 hexadecimal values, e.g. 2001: | ||
+ | |||
+ | This brings the capability to uniquely identify any device connected to the Internet using its IPv6 address. Regarding IoT, implementations have many drawbacks (IPv4 also has them). IPv6 network is star-like, whereas IoT networks can benefit from the mesh model. IPv6 network requires a controller providing free addresses (a DHCP server) – devices need to contact it to obtain the address. Every single IoT device needs to keep a list of devices it corresponds with (ARP) to resolve their physical address. Moreover, full IPv6 stack implementation requires large RAM, when used. | ||
+ | |||
+ | === 6LoWPAN === | ||
+ | The name is the abbreviation of “IPv6 over Low-Power Wireless Personal Area Networks” ((Jonas Olsson, „6LoWPAN demystified”, | ||
+ | This protocol was introduced as a lightweight version of full IPv6, IoT-oriented. | ||
+ | This feature allows connecting 6LoWPAN networks with other networks using so-called Edge Router. Thus every node can be visible on the Internet as states in IoT idea. This standard has been developed to operate on the radio channel defined in 802.15.4 (as ZigBee, Z-Wave). It creates the adaptation layer that allows using IPv6 over 802.15.4 link. | ||
+ | 6LoWPAN has been adopted in Bluetooth Smart 4.2 standard as well. | ||
+ | |||
+ | 6LoWPAN supports two addressing models: 64 bit and 16 bit (that, of course, limits the number of devices connected to one network to 64 000 nodes). The primary frame size is just 127 bytes (comparing to full IPv6 where it is 1280 bytes at least). 6LoWPAN supports unicast and broadcast. It also supports IP routing and link-layer mesh (802.15.5) that enables the introduction of the fail-safe redundant, self-organising networks, because the link-layer mesh can have more than one Edge Router. | ||
+ | 6LoWPAN uses autoconfiguration for neighbour devices discovery so does not require a DHCP server. It also supports ciphered transportation using AES 128 (and AES 64 for constrained devices). | ||
+ | |||
+ | <figure Sample_6LoWPAN> | ||
+ | |||
+ | {{ : | ||
+ | < | ||
+ | </ | ||
+ | |||
+ | 6LoWPAN devices can be just nodes (Hosts) or nodes with routing capability (Routers) as presented in Figure {{ref> | ||
+ | |||
+ | A gateway between 6LoWPAN and regular IPv6 (IPv4) network is implemented by the Edge Router. Its purpose is to translate " | ||
+ | |||
+ | When the 6LoWPAN network starts, there are three operations done, repeated consequently. | ||
+ | - Commissioning – establishes connectivity on the Data Link Layer level between nodes. | ||
+ | - Bootstrapping – performs address configuration, | ||
+ | - Route Initiation – executing routing algorithms to set up paths. | ||
+ | Typical IPv6 networking discovery won't work here because multicast/ | ||
+ | |||
+ | An interesting procedure is performed when an IoT node (device) wants to connect to the existing 6LoWPAN network. As there is no central DHCP server broadcasting information, | ||
+ | |||
+ | Network discovery (discovery of neighbour nodes) in 6LoWPAN uses four principals: | ||
+ | * NR – node registration, | ||
+ | * NC – node confirmation, | ||
+ | * DAD – duplicate address detection, | ||
+ | * support for Edge Routers. | ||
+ | |||
+ | |||
+ | <figure 6LoWPAN_Discovery> | ||
+ | {{ : | ||
+ | < | ||
+ | Discovery demystified.</ | ||
+ | </ | ||
+ | |||
+ | Network Automated Discovery is composed of two main sections. | ||
+ | - Part one (dark blue) – Neighbor Discovery (ND): | ||
+ | * new node sends RS multicast (SLLAO); | ||
+ | * all routers respond unicast RA (PIO + 6CO + ABRO + SLLAO); | ||
+ | * node selects one router as default (usually first RA obtained) and derives global Ipv6 address based on prefix delivered (PIO); | ||
+ | * node sends ARO (ARO + SLLAO) unicast to the selected router; | ||
+ | * router returns ARO with a status: | ||
+ | * status is: OK, Duplicate Address, Cache Full, other (see RFC5226); | ||
+ | * assuming status OK, the router adds new neighbour node address into the cache; | ||
+ | * Node sends periodically NS to inform that “it is alive” the router (so-called NUD (Neighbor Unreachability Detection)); | ||
+ | * Process above may involve DAD (Duplicate Address Detection) mechanism to be triggered. | ||
+ | * on registration, | ||
+ | * DAD message is expected to “wake up” IoT device from standby mode! | ||
+ | - Part two (red) – Network Registration (NR): | ||
+ | * node sends DODAG Solicitation (DIS) unicast to the router. | ||
+ | * router responds with DODAG Information Object (DIO) and keeps broadcasting it periodically. DIO contains router rank (i.e. it presents, how far the router is from the Edge Router); | ||
+ | * if node obtains DIO with better rank, it should re-register with other “better” router as a new default router; | ||
+ | * finally node sends Destination Advertising Object (DAO) to its default router that is forwarded to edge router; | ||
+ | * edge router responds with DAO ACK. | ||
+ | |||
+ | This way, the new 6LoWPAN node can join the new network seamlessly. Moreover, this mechanism enables 6LoWPAN mesh network to self-organise itself if needed, e.g. in case of a failure of the router. | ||
+ | ===== ===== | ||
+ | <box # | ||
+ | <box # | ||
+ | ===== Host Layer Protocols ===== | ||
+ | <box # | ||
+ | <box # | ||
+ | |||
+ | The host layers protocols include session (SES), presentation (PRES) and application (APP) level, particularly APP (application) layer in the regular Internet communication is dominated by the HTTP protocol and XML-related derivatives, | ||
+ | Some IoT designed protocols are reviewed below. | ||
+ | |||
+ | ==== MQTT ==== | ||
+ | MQTT protocol ((https:// | ||
+ | |||
+ | MQTT uses TCP connection so requires open connection channel (this is in opposite to UDP connections, | ||
+ | |||
+ | The standard MQTT Message header is composed of just two bytes only (Table {{ref> | ||
+ | |||
+ | <table MQTT_header> | ||
+ | < | ||
+ | ^bit ^ 7 ^ 6 ^ 5 ^ 4 ^ 3 ^ 2 ^ 1 ^ 0 ^ | ||
+ | |byte 1 | Message Type |||| DUP flag | Qos level || RETAIN | ||
+ | | byte 2 | Remaining length | ||
+ | </ | ||
+ | |||
+ | |||
+ | |||
+ | |||
+ | MQTT requires for its operation a centralized MQTT broker that is located outside of firewalls and NATs, where all clients connect, send and receive messages via **publish/ | ||
+ | <figure mqtt_broker> | ||
+ | {{ : | ||
+ | < | ||
+ | </ | ||
+ | |||
+ | ===MQTT Message=== | ||
+ | MQTT is a text-based protocol and is data-agnostic. | ||
+ | A message is composed of a Topic (text) and a Payload (data). | ||
+ | The topic is a directory-like string with slash ("/" | ||
+ | The subscriber can subscribe to specific, single Topic, or to a variety of Topics using wildcards, where: | ||
+ | * # stands for the entire branch, | ||
+ | * + stands for the single level. | ||
+ | |||
+ | //Example Scenario// | ||
+ | |||
+ | Publishers deliver some air quality information data in separate MQTT messages and for various rooms at the department Inf of the Universities (SUT, RTU, ITMO) to the Broker: | ||
+ | ^ Topic (publishers): | ||
+ | | SUT/ | ||
+ | | SUT/ | ||
+ | | SUT/ | ||
+ | | RTU/ | ||
+ | | ITMO/ | ||
+ | | RTU/ | ||
+ | | SUT/ | ||
+ | | RTU/ | ||
+ | |||
+ | The subscriber 1 wills to get all sensor data for SUT university, Inf (informatics) department only, for any space: | ||
+ | ^ Topic (subscription): | ||
+ | | SUT/ | ||
+ | The subscriber 2 wills to get only Temperature data virtually from any sensor and in any location in ITMO: | ||
+ | ^ Topic (subscription): | ||
+ | | ITMO/#/ | ||
+ | The subscriber 3 wills to get any information from the sensors, but only for the RTU | ||
+ | ^ Topic (subscription): | ||
+ | | RTU/# | | ||
+ | |||
+ | The payload (data) of the message is text as well, so in case one need to send binary data, it is necessary to encode it (e.g. Base64). | ||
+ | |||
+ | ===MQTT Broker=== | ||
+ | MQTT Broker is a server for both publishers and subscribers. The connection is initiated from the client to the Broker, so assuming it is located outside of a firewall, it breaks firewall its boundaries. | ||
+ | The Broker provides QoS (Quality of Service), and it can retain message payload. There are three levels of MQTT Broker QoS (supplied in the message level). | ||
+ | * Unacknowledged service: Ensures that MQTT message is delivered at most once to each subscriber. | ||
+ | * Acknowledged service: Ensures delivery of the message at least once to every subscriber. The broker expects acknowledgement to be sent from the subscriber. Otherwise, it retransmits data. | ||
+ | * Assured service: This is two-step delivery of the message, and ensures the message is delivered exactly once to every subscriber. | ||
+ | For Acknowledged and Assured services it is vital to provide unique packet IDs in MQTT frame.\\ | ||
+ | |||
+ | The DUP flag (byte 1, bit 3) represents information sent by the publisher if the message is a "first try" (0) or a retransmitted one (1). It is mostly for internal purposes, and this flag is never propagated to the subscribers. | ||
+ | |||
+ | MQTT offers some limited set of features (options): | ||
+ | * clean session flag for durable connections: | ||
+ | * if set //TRUE//, Broker removes all of the client subscriptions on client disconnect; | ||
+ | * otherwise Broker collects messages (QoS depending) and delivers them on client reconnecting; | ||
+ | * MQTT " | ||
+ | * message retaining: it is a feature for regular messages. Any message can be set as retaining and in such case Broker will keep the last one. Once a new client subscribes topic, it will receive a retained message immediately even if the publisher is not publishing any message at the moment. This feature is **last known good value**. It is good to present publishers state (e.g. publisher sends retained message meaning " | ||
+ | |||
+ | Interestingly MQTT is a protocol used by Facebook Messenger ((https:// | ||
+ | |||
+ | MQTT security is rather weak. MQTT Broker can offer user and password verification yet it is sent plain text. However, all communication between client and Broker may be encapsulated in SSL, encrypted stream. | ||
+ | |||
+ | A short comparison of MQTT and HTTP protocols are presented in the Table {{ref> | ||
+ | <table http_vs_mqtt> | ||
+ | < | ||
+ | | ^ MQTT ^ HTTP ^ | ||
+ | ^ Design | ||
+ | ^ Pattern | ||
+ | ^ Complexity | ||
+ | ^ Message size | Small, with 2 byte binary header | ||
+ | ^ Service levels | ||
+ | ^ Implementation | ||
+ | ^ Data distribution models | ||
+ | </ | ||
+ | |||
+ | ==== CoAP ==== | ||
+ | |||
+ | CoAP protocol (RFC7252) originates from the REST (Representational State Transfer). CoAP does not use a centralised server as MQTT does, but every single device " | ||
+ | * %%" | ||
+ | * a secure, encrypted version uses " | ||
+ | It supports various content types, can work with proxy and can be cached.\\ | ||
+ | The protocol is designed to be compact and simple to implement. The stack implementation takes only about 10 kB of RAM and 100 kB of storage. The header is only 4 bytes. | ||
+ | |||
+ | CoAP protocol has a binary header to decrease overhead but payload depends on the content type. Initial, non-exclusive list of the payload types include: | ||
+ | * text/plain (charset=utf-8) (ID=0, RFC2046, RFC3676, RFC5147), | ||
+ | * application/ | ||
+ | * application/ | ||
+ | * application/ | ||
+ | * application/ | ||
+ | |||
+ | CoAP endpoint services are identified by unique IP and port number. However, they operate on the UDP instead of TCP (like, e.g. HTML does). The transfer in CoAP is made using non-reliable UDP network so that a message can appear duplicated, disappear or it can be delivered in other order than initially sent. Because of the nature of datagram communication, | ||
+ | CoAP messages can be (non-exhaustive list): | ||
+ | * CON (Confirmable, | ||
+ | * NON (Non-Confirmable, | ||
+ | * ACK (an acknowledgement message), | ||
+ | * RESET (sent if CON or NON was received, but the receiver cannot understand the context, e.g. part of the communication is missing because of device restart, messages memory loss, etc.). Empty RESET messages can be used to " | ||
+ | |||
+ | Because of the UDP network characteristics, | ||
+ | * stop and wait for retransmission with exponential back-off for CON messages, | ||
+ | * duplicate message detection for CON and NON-messages. | ||
+ | Request-reponse pair is identified by a unique " | ||
+ | Sample request-response scenarios are presented in images below. | ||
+ | Sample CoAP message exchange scenarios between client and server are presented (two per image) in Figure {{ref> | ||
+ | <figure CoAP1> | ||
+ | {{ : | ||
+ | < | ||
+ | </ | ||
+ | <figure CoAP2> | ||
+ | {{ : | ||
+ | < | ||
+ | </ | ||
+ | The scenario in the Figure {{ref> | ||
+ | The scenario in Figure {{ref> | ||
+ | The scenario in Figure {{ref> | ||
+ | The scenario in Figure {{ref> | ||