Hello pupil! We hope you are doing well with object-oriented programming with Python. OOP is an extremely important topic in programming, and the good thing about Python is that the concept of OOP can be implemented in it. In the previous lecture, we made a basic introduction to all the elements that are used in the OOP, and right now, we are moving forward with the detail of each concert with examples. The imperative nature of the OOP is useful for us because it uses the statements to change the programming state, and in this way, the working of the code becomes easy and effective. To use the applications of Python, the imperative nature of OOP will give us the tools we need to get the perfect results by using our creativity. We will prove this in just a bit, but here are the highlights of the topics that will be discussed.
How can you describe the OOP by using an example?
Why are classes important in OOP?
Discuss the example and syntax of code when we use classes in OOP.
What are objects?
Give us an example where multiple objects are made if one class and the information are given by the user.
Discuss the basic features of objects in OOP.
How do you classify the attributes of objects?
What are the behaviours in OOP?
All of these are important to learn so pay attention to each and every concept and if you have any confusion, you can contact us directly.
Before going into the details of the OOP, now is the time to discuss why we are emphasizing the importance of the OOP and how we explain it with Python. The whole concept will be clear with the help of the following example:
Think of a dog that will be taken as an example by a class. Here, we have taken a general example that is common in the real world. Think of all the characteristics of the dog that may be either physical or natural habits of the dog. The general class of dog may have many types, such as the breed of the dog. There are hundreds of breeds of dogs, and these are considered the basic members of the class "dog."
Moreover, different dogs have different kinds of attributes such as their size, colour, skin type, age, and other characteristics that are said to be their instance attributes. On the basis of these attribute, the division of the dogs is done into different classes.
Moreover, the way the dogs bark, their favourite food, and their daily routine make them more specific, and these are referred to as the methods of that particular class.
The class is the basic unit, without which, the programmers may not think about the OOP in any way. This is the prototype with which the whole OOP process is carried out. You can think of a class as the blueprint of the house (let's say). In this way, the information about the floor, walls, rooms, windows, doors, etc. In this way, the whole house is made by following this blueprint(class) whereas, the result, that is the house is the object. Let us prove all this information with the help of this example.
The class is simply made in Python with the keyword “class” and the name that we want for our class:
class myClass:
# class definition
Here,
class=keyword
myClass= the name of the class given by the programmer.
In this way, with the help of simple lines, the creation process of the class is carried out. Now, the definition of the class is in the new line. To make a clear difference, a colon is used after the name of the class. You must keep in mind, the class name is a single word, no matter what the length of the name, and there must be no space between the name of the class.
In the example of the class given above, where we were talking about dogs. We are using the same example and will show you the result by using them in the example. To start with a simple example, the class with only three attributes.
#declaring the class
class myDog:
#defining attributes
def __init__(self, name, age):
#using the attributes and storing them in the new names
self.name = name
self.age = age
#usign the stored name to print the results
tinku = myDog("Tinku", 2)
print("The name of the dog= ",tinku.name)
print("The age of the dog= ",tinku.age)
Let's see what happens during this code:
First of all, we created a class with the class keyword, and this time, we named it “myDog” so you are providing the information about your dog( if you do not have it, just imagine it) and we are writing the particular features of that dog. So, the class is myDog, and all the other features are its attributes.
In the next step, we are defining the characteristics with which we want to describe our dog. Here, name and age are the attributes. That is taken as one of the two arguments we are defining to use later.
The "self" keyword will tell us that name and age are the special attributes that we want to use here.
In the end, a new unit is formed, where this time, we are using the values of attributes instead of the names. The first step was only to give the base of what we wanted, and this time, we will assign values to these attributes.
You can see, the name is in the form of a string, therefore we have used a double quotation. In this way, we do not have to specify the data type but just represent it in a specific way.
In the end, it's time to print the result and to make the message clearer, we used the written message and then declared the value we wanted.
We can add more and more attributes to make the class clearer and store data about the dog, such as its colour, fur type, etc. This is a simple example to show you how the class works.
The workings of the class are not just limited to one product. This is the good thing about the OOP is, it provides us with the versatility to work in a different way with the same code. In the example given above, if more than one breed of dog is to be stored, then we will make the objects of the class "dog."
To understand the objects in interesting ways, we are moving towards real-time applications where different objects are made and then used in a specific way. Let us take an example where we have different types of dogs with different ages, and the combination of the ages of the first two dogs is the age of the third dog. So here is the question that can be asked of you in the examination.
Write the code to get the age of a dog that is the combination of two dogs and get the input from the user for it.
#declaring the class
class myDog:
#defining attributes
def __init__(self, name, age):
#using the attributes and storing them in the new names
self.name = name
self.age = age
#using attributes in string message
def dogInfo(self):
print(self.name + " is " + str(self.age) + " year(s) old.")
#printing queries and getting input from user
print("What is the age of happy")
AgeOfHappy=input()
print("What is the age of sunny")
AgeOfSunny=input()
AgeOfFancy=int(AgeOfHappy)+int(AgeOfSunny)
#using the inputs to guess the age of fancy
print("Age of fancy= ",AgeOfFancy)
#printing results
happy = myDog("Happy", AgeOfHappy)
sunny = myDog("Sunny", AgeOfSunny)
fancy = myDog("Fancy", AgeOfFancy)
happy.dogInfo()
sunny.dogInfo()
fancy.dogInfo()
This program has many interesting features, and these will become clear with the help of this discussion.
At the beginning of the program, the class “myDog” is created so that we may give the same attributes to different objects.
To declare the attributes we are using here the “def” keywords to define the keyword then the
Attributes are mentioned so that we may use them later.
The next step is to define the message, in which we will use the attributes and get the result in the form of a message. Here, the point to notice is, we are using the string keyword for the "age,” but how can age be a string? Actually, we are using it in the string message, and if we declare the “int” here, the compiler, when it reaches this point at the output, will throw the error and not print the whole string.
After that, the whole mechanism is used in which we are printing the message to input the age of the first two dogs and get the output in the form of integers.
Here, if the user inputs a data type other than an integer, it will also result in an error.
Both these ages are then added, and the result is saved in the “AgeOfFancy” variable.
The object we have just used to print the results.
So with the help of this discussion, we come to know that the object consists of the following features:
Each object has its own set of attributes, which are variables that store information about the object's current state. We can say that objects are made of attributes. Yet, there are different types of attributes in OOP, and the following are some of the most important characteristics of attributes:
Instance variables: These are defined within the class but are unique to every instance of the class.
Class variables: These are also defined within the class but are shared with all the instances.
Methods: These are used to manipulate the object’s state and are defined within the class to operate the attributes.
Special methods: These are also referred to as the magic methods and these tell the compiler how objects will behave under certain conditions. These are denoted by the double score in the name as we have just used in the previous code of dogs.
Inherited attributes: These are used to reuse the modularity in the code as these are inherited by a subclass or a superclass. So it makes working easy.
When an object is created in OOP, it has its own set of behaviours, which are defined by the methods in its class. These methods can be used to change the state of an object. Another function of the behaviour is to carry out other operations related to the object's behaviour. For example, if we declare the object of a car, we might have methods such as:
start engine()
accelerate()
brake()
turn()
These methods define the behavior of the car object and enable it to perform the actions that are expected of a car. These are just simple examples, and we can add more and more behaviors, just as a car can do hundreds of tasks.
Hence, in this lecture, we read a lot about objects and classes. There are different entities that are used in OOP, and objects and classes are the basics. We must know that objects and classes are used simultaneously, and for a better understanding, we learned the classes first and then examined where and how objects are being used. Moreover, different types of objects and fundamental knowledge about their pillars are discussed here. We have a lot of information to share with you, and you must have noticed that Python is now more complex but useful when we use the concepts of OOP. We have some mini Python projects to share with you in this tutorial, so stay with us for more programs.
Hey peeps! Are you excited to begin with the new chapter in Python? Till now, we have been learning the data types and their related concepts. Now, we are starting a new chapter where you will learn the details of Object Oriented Programming or OOP. We are moving towards the advanced level of programming in Python, and here, you will go through the complex but interesting concepts that will show us the fascinating results on the screen. This will be more clear when you will know the basic information about the OOP, but before going deep, we will go through the headlines of the lecture:
How do you classify the programming languages?
How do you introduce the OOP?
Why object-oriented programming is important in Python?
How do you define class and objects in OOP and how are they connected?
What are polymorphism and encapsulation?
How do you use the inheritance in OOP?
How do you understand data abstraction in OOP?
What does method overloading mean?
Keep in mind, it is not a specific concept with Python but any higher-level programming language that supports the OOP has the same concepts and we are using a very general way to describe all the concepts.
Before going into the detail of this topic, it is helpful to understand why we are emphasizing on the OOP and its importance. Actually, there are different types of programming languages and being a programmer, you must know the basic categories. Some of the important types of programming languages are:
Procedural Programming Language
Functional Programming Language
Object-oriented Programming Language
Scripting Programming Language
Logic Programming Language
Out of which, we are interested in the OOP. The reason why the type of programming language is important, it describes the paradigm of the language, and therefore, we can understand the nature and the importance of that particular language in the profession you are using it for. Here, we should know what exactly the “paradigm” means:
“A programming paradigm is the concept to which a programming language's methodology adheres."
Paradigms are significant because they define a programming language and its operation. The classification of the programming languages is done by keeping its paradigm in mind and in this way, the programmer may choose the type of programming language that exactly suits the application for which the coding is required.
You can see that OOP comes in the imperative paradigm. In imperative programming, the user typically interacts directly with the computer's state, deciding how things should be calculated. In this way, more control is in the programmer’s hands, which is the basic source of attraction towards this programming language. In the practice of programming, I am sure you have touched other types of languages as well at any point. So, it becomes easy to compare and practice the code.
In real-time education, different types of subjects are taught to us by teachers. We are moving from basic to advanced programming in this course; therefore, we have covered the concept of data types before. This time, the OOP is our source of attraction, and we are going to learn it deeply because the programmers, most of the time, deal with the OOP when they are using the practical applications of the programming. Let us look at the introduction to the OOP:
“OOP (Object-Oriented programming) is a programming paradigm that organizes and structures code using objects and classes.”
For now, do not bother about the special terms used in this definition. We will learn a lot about them in these lectures with the help of different terminologies. Hence, if anything is causing confusion, do not worry because everything will be clear in just a bit.
The concept of OOP is so vast and important that it is widely used to write powerful applications. The data engineers have to write these applications to access and use the data stored in different entities.
The feature that makes the OOP unique is, it uses concepts that not only make the programming easy but efficient. It is based on the imperative programming paradigm, which employs statements to alter the state of a program. It is concerned with describing how a program should work. One must keep in mind that the main objective of the OOP is to bind the data and the functions of the program in such a way that all of these may work as a single unit but the security of the data remains intact. There are some important terms that you will see often in these lectures, so have a look at all of them.
Class
Objects
Polymorphism
Encapsulation
Inheritance
Data Abstraction
Keep in mind that you have to grasp the concept of each of these terms clearly so that, when you read them with other types of definitions, you may not be confused. You will learn all of these in detail in the coming lectures, but the basic introduction to all of them is given next:
Before going into the introduction of the OOP, one must know that an object is an instance of a class. Object and class are interconnected terms, and a class is defined as:
“In OOP, a class is a basic unit that represents the collection of objects, and it can be thought of as the blueprint or the prototype by following which, the objects are made.”
The attributes of a particular thing, connected with each other, can be represented with the help of the class, where the number of the attributes starts at one and can be two, ten, or any other positive number. In this way, a simple and basic class can be used to store all types of physical or logical information about a particular product.
In object-oriented programming, objects are the basic units of data. An object is associated with the class and is the entity with which the state and behaviour of the class are associated. If it is confusing at this point, do not worry because we are going to discuss the object in detail and will work again and again with the objects.
The good thing about the objects in OOP is that, just like the real-time concept of objects, the programming objects may be anything, whether it is physical, such as a car, an animal, a plant, a cooking item, any food, or any other thing, or abstract, such as any software, a bank account, a soft blueprint, or any document. The positive thing about the object is, it allows us to reuse the same code anywhere in any block of the same code where the same attribute of the object is to be used.
The fundamental concept of the OOP is polymorphism, and it has the same features as the family in real life. To keep things simple, we assume that all the objects belong to the same class, and the polymorphism allows us to use the objects together as they are from the same family. In this way, the same objects can be used interchangeably in the same context. In this way, the workload of the programmer is minimized as much as possible through polymorphism. In simple words, the concept of polymorphism is the same as it is in chemistry, where the same element can be used in different ways when certain conditions are met.
Another feature that makes the polymorphism attractive is the availability of the alteration in the classes, both in terms of their size and the data stored in them. All this information will be cleared up in the coming lectures, but for now, we only understand the basics of polymorphism. In other words, we all know that poly means "many,” and if we talk about OOP, it includes the concept of a class's ability to get the features of already existing classes in this way. For example, you can assign the attributes of a particular product, such as a car, to another car with the same basic features but with different attributes. This is just a basic example of polymorphism, and many people mix this concept with inheritance, but these are different, and you will learn a lot about them in the next lectures.
The next concept that we are going to discuss is encapsulation, and to make your concept clear, let us take the example of the capsules that we get from the pharmacy for different health issues. These capsules protect the inner medicine, and the same concept can be applied to this type of encapsulation to reinforce the concept. Basically, the data is protected with the help of different concepts used in the encapsulation.
The programmers are very sensitive about their codes and the data stored with the help of these codes. Encapsulation is used to give the code privacy and protect it from unwanted users. The private attributes of the code that are enclosed in the capsule are only accessible by the programmer itself. In other words, we cannot use the private attribute in other blocks of code until the programmer himself allows it.
Another important feature of the OOP is inheritance, and this is the point where we can say that the OOP is making Python more effective and easier to use. It is one of the most significant points of the OOP, and with the help of easy and effective Python, programmers can inherit the characteristics and attributes of any class and assign them directly to others. For this, you have to learn about the child and parent classes, but for now, we are leaving this topic here and moving on to the next point that will show us the importance of the OOP, especially when we use it in Python.
If you are interested in becoming a professional programmer, then some points should always be kept in mind, and the most important one is to always go with clean code that precisely describes the code and gives the exact coding without any errors. For this, some concepts will help you a lot, and one of them is the concept of data abstraction. With the help of this concept, the programmer is able to code cleaner because "data abstraction" means writing cleaner code and hiding unnecessary details from the users. It is yet another method for the programmer to maintain privacy from the end user. THE SENSITIVE CODES ARE HIDDEN FROM THE OTHER USERS USING DIFFERENT TECHNIQUES. The whole process of data abstraction revolved around making and implementing the abstraction classes and then calling them in different ways according to the requirements of the code.
Here is a small topic to be discussed that is not a particular part of OOP in Python, but almost every programming language that works with OOP has it. This is also true for other characteristics that we have discussed so far.
In method overloading, many methods with the same name are declared and then called at once. In this way, a single class can take multiple arguments. Other concepts, such as method overriding, are also connected with the same concept, and we will discuss them with some suitable examples.
Consequently, we have almost all the basics of the OOP. We have read a lot about them and tried to make them more general so that the programmers working on them other than Python may also get the useful concepts from this lecture. Actually, the OOP is not just confined to Python, but we have to connect it with Python, and this will be more fully discussed in the next lectures, where all these concepts will not only be discussed but the practical implementation of codes will help us to have a grip on Python. This is an extremely useful topic and therefore, we will move a little bit slowly on these lectures and will understand each and every point in detail.
Hey peeps! Welcome to the new tutorial for the Python programming language, where we are at the point where we are going to learn about the loops. Loops are fundamental concepts in programming, and if we talk about Python, there is a smaller variety of loops in it, but the most important ones are available to practice in Python. In the last session, there was a long discussion about the while loop in detail. We had seen some examples and the details of the statements that can be used within the while loop. In the present lecture, we are going to discuss the second type of loop in Python, that is, the for loop. You will go through the training of every important and basic step about this loop, but first of all, you have to look at the basic list:
Why do we prefer for loop over some other concepts in Python programming language?
What are some basic concepts that every programmer must know about the for loop in Python?
Describe the flow chart of the for loop.
What are some examples that explain the for loop in Python?
How do we use different sequences in the for loop?
What is the range function explain it in detail by using the for loop in Python?
There are other ways to get the same output as we will get in this lecture but using the for loop is one of the easiest and most fundamental ways to get the best results. Have a look at the detail of each question.
The for loop is the basic looping process in Python that is extremely useful in making the basic to higher level codes in simpler way. We all had the introduction of the For loop in the previous lesson, and now, have a look at the following positive points about this loop:
The for loop makes the code very simple and the programmers do not have to pay much attention to make the logic. You can get the idea of its simplicity that the user can initiate the loop in just a single line if all the logic is clear in it. After that, the body of the loop starts. Just like other loops, the For loop gives us the independence to adjust the flow of the code so that we do not have to write the same block of the code again and again.
Different data types can be used in the for loop and the best thing about it is, it becomes super easy to use the For loop to manage the sequences. It would not be wrong to say that For loop makes the working of the sequence best therefore, for loop is perfect for the sequences such as lists, tuples, and arrays. Moreover, the traversing of the sequences is easy with the For loop.
The for loop is not a new concept but in the old higher-level programming languages such as C and C++, for loop is used therefore if a programmer is moving from such basic programming languages to Python, the concept will be cleared before they start it. In other words, the for loop is a generic type of loop that once understood, can be useful as well when they switch to the new programming language.
We know the introduction of the for loop but this time, we are going to discuss the detail of every process that will be useful in the practical coding using the for loop. Keep in mind, loops are the statements and not the whole code. This helps to manage the code in a better way and to reuse the same block by merely inserting it in the body of the loop.
We are discussing the generalized form of the For loop and therefore, all the concepts are very general that we have discussed till now. Yet, the only difference in the coding is the syntax of the loops and therefore, we are discussing it at first to get an idea of what actually is going on.
for iterator in sequence:
statement(s)
It seems very simple here but the statement is not that much simple. The programmers, then using the for loop add multiple statements in different ways to get the required output. More things will be cleared when you will see the flow chart.
The best way to get the concept of the for loop is to check for the flow chart of this loop. Have a look at the picture given next and then we will move towards its discussion.
Here, you can compare the syntax and flow chart and get an idea of what happens when data is input in the for loop. At the start, when the condition is applied on the for loop, the compiler checks for the condition if it is true or not and as you can guess, if the condition is true, the compiler will check for the body code
Different data types can be used with the for loop and we will move from basic to complex ones. We all know about the string; therefore, here is the first example with the string message.
#initializing the message
message= print("Enter the string")
#taking input from the user
str=input(message)
#using for loop to print the message from the user
for i in str:
print(i)
Here, when we run the program, we get the dialogue box it says the “none” word with the dialogue box. This will look strange but it makes sense. With some functions in Python, the return value is mentioned in the output. Since this function will not return any result but will only give us the same string that we are going to input in it, therefore, there is the word “none” mentioned in the dialogue box. We can solve it in different ways but the point I want to make here is to clarify the reason behind this indication.
When the string message is typed by the user, the same message with the same format is shown on the screen but this time, as we are using the for loop, each character is picked by the compiler one after the other and therefore, the result will be obtained in the vertical form with each character at the new line.
Here, you can see the “none” is added by default without a string message and once it is printed, the for loop picked each character and printed it in a separate line. Even the spaces between the words are counted, and we get a clean and understandable output.
Have you tried the code given above? If yes then there must be a question in your mind that what happens if we input any other data type instead of string? Actually, this is not a precise code yet, if we add the restriction to add only the string as we have done in the previous lecture, the compiler will not accept any other data type other than string. Yet, to keep things simple, I am not changing the code as the main focus is on the for loop till now.
Here comes the practice that is specialized in the for loop. Since the beginning, you have been noticing that we are emphasising the sequences. We all have practised them and in some examples, the for loop was used before but since this is a pure practice of the for loop, I have made a program that contains all important sequences in a single program.
#initializing the List to use with the For loop
print("\b Names of the fruits")
fruits= ["strawberry", "cherry", "blueberry", "apricot", "tomato"]
for i in fruits:
print(i)
#initializing the tuple to use with the For loop
print("\b Price list of mentioned fruits")
priceOfFruits= (34.8, 11.7, 126.9,11.6,11.5,22.0,1)
for i in priceOfFruits:
print(i)
#initializing the array to use with the For loop
print("\b Random things and numbers")
items= {"lipstick",3,"papers", 3, "pen", 1, "bread", 3.4 }
for i in items:
print(i)
Hence, the program is clear as we have practised it before. The type of bracket represents each sequence and it has its own characteristics. For loop access each and every element of the sequence and print it on the screen. The arrangement of the items in the array is random and we can not suggest the sequence of the elements because it randomly picks the elements and print them. Hence, every time we run the code, the value stored in the variable i is different and the one, printed on the screen, is never repeated at that particular run time.
The next topic here is the range function that has interesting applications in the fields like gaming. It is because it can be used in different ways as it has the independence of the number of parameters. The syntax of the range function is the same with the for loop as it is with other statements.
x=range(start, stop, step)
Where,
x=name of the variable in which the value of the range is being stored.
start=starting point of the series
stop=ending point of the series
step=The interval between the range member.
Keep in mind, you can use one, two, or three parameters at the same time according to your easiness. Instead of using separate examples for each case, we have designed a program that describes the all. Have a look at the code and then we will discuss it more.
#using the range function to print the table
num = int(input("Enter the integer for which the table is required? "))
for i in range(1,21):
print(num,'x',i,'=',num*i)
#range function with one parameter
print("\b using the range function with only ending point")
for i in range(7):
print(i)
#range function with two parameters
print("\b using the range function with starting and ending points")
for i in range(2,9):
print(i)
#range function with three parameters
print("\b using the range function with start,end, and step points")
for i in range(1,10,3):
print(i)
For your convenience, we will go through the basic to the complex concepts.
The three parameters are useful to get a uniform series of numbers.
Only integers can be used with the range function.
If the start point is not mentioned, it always starts from zero.
The stop parameter is the compulsory one to use in the range function.
To make the restriction of only integers, the “int” keyword is used with the input function in a specific syntax.
You can get the table of any number with the range of any integer easily using the range function.
For loop is the best way to get the required output from the range function.
Consequently, we can say that we are not beginners and instead of learning the long theories about the basic concept, the focus of our lecture was towards the practical examples of the for loop therefore we started this lecture with the introduction and then moved towards the basics, syntax, examples, and the codes using different data types. As the specialized data type of the for loop is sequence, therefore, we had the practice of the for loop with the sequences. Using the range function with for loop gave us the interesting outputs and with the help of these examples, we learned the for loop in a better way. The upcoming lectures are interesting tooo so keep practicing and stay with us.
Hello friends, I hope you all are doing well. Welcome to the next tutorial of our Raspberry Pi 4 programming course. In the previous lecture, we interfaced LCD 16x2 with Raspberry Pi 4. Today, we will interface a keypad 4x4 to Raspberry Pi 4. In embedded projects, a keypad is used to get user input i.e. calculator, ATM keypad etc. Different types of Keypads are available i.e. 4x4, 4x3 etc.
So, let's get started:
We will need the following components in our today's project:
Any microcontroller's GPIO can be used to power a keypad; thus, there's no need for an additional power supply. A pulse must be sent from the Raspberry Pi to all four rows of the Keypad to determine which button was pressed. If the user pushes a button associated with the currently pulled high line, the column associated with that line will be pushed high.
The pressed button can be identified by deciphering the sequence of rows and columns. When a user hits the B button in the second row of the fourth column, Pi 4 will send a pulse to the second line and then see which of the four columns was pulled high to determine which button was pressed.
The graphic above depicts the reasoning behind how we will interpret the keys pressed on the Keypad. As indicated, the membrane switches are laid out in a matrix.
Following the iteration of each row, columns are set back to High.
I hope you understood the working of the keypad. Now let's interface our Keypad with RPi4:
We don't need to provide any power pins to these keypads. Simple, connect the Keypad's eight data pins to the RPi4's GPIO pins:
Like the image up top, I used a monochromatic color palette. The rows are denoted by the blue connections, while the orange ones show the columns.
After connecting the pins as described above, the next step is to run a test program that outputs the Keypad's button push to the Raspberry Pi 4's console.
# GPIO setup and imports omitted
def readLine(line, characters):
GPIO.output(line, GPIO.HIGH)
if(GPIO.input(C1) == 1):
print(characters[0])
if(GPIO.input(C2) == 1):
print(characters[1])
if(GPIO.input(C3) == 1):
print(characters[2])
if(GPIO.input(C4) == 1):
print(characters[3])
GPIO.output(line, GPIO.LOW)
try:
while True:
readLine(L1, ["1","2","3","A"])
readLine(L2, ["4","5","6","B"])
readLine(L3, ["7","8","9","C"])
readLine(L4, ["*","0","#","D"])
time.sleep(0.1)
except KeyboardInterrupt:
print("\nApplication stopped!")
In the above code, we have a readLine command, which reads the rows one by one and checks if the button is pressed. If any button is pressed, the digit will appear in the Pi Console. The approach also requires a dictionary of button-to-symbol correspondences.
You can think of this code as a basic demo. You can't even press and hold a button and have it register that. Each pulse it transmits on the output line will identify a new keystroke.
Below is a program that can accurately identify individual key presses and use them to activate a basic code lock.
import RPi.GPIO as GPIO
import time
L1 = 5
L2 = 6
L3 = 13
L4 = 19
C1 = 12
C2 = 16
C3 = 20
C4 = 21
keypadPressed = -1
secretCode = "4789"
input = ""
GPIO.setwarnings(False)
GPIO.setmode(GPIO.BCM)
GPIO.setup(L1, GPIO.OUT)
GPIO.setup(L2, GPIO.OUT)
GPIO.setup(L3, GPIO.OUT)
GPIO.setup(L4, GPIO.OUT)
GPIO.setup(C1, GPIO.IN, pull_up_down=GPIO.PUD_DOWN)
GPIO.setup(C2, GPIO.IN, pull_up_down=GPIO.PUD_DOWN)
GPIO.setup(C3, GPIO.IN, pull_up_down=GPIO.PUD_DOWN)
GPIO.setup(C4, GPIO.IN, pull_up_down=GPIO.PUD_DOWN)
def keypadCallback(channel):
global keypadPressed
if keypadPressed == -1:
keypadPressed = channel
GPIO.add_event_detect(C1, GPIO.RISING, callback=keypadCallback)
GPIO.add_event_detect(C2, GPIO.RISING, callback=keypadCallback)
GPIO.add_event_detect(C3, GPIO.RISING, callback=keypadCallback)
GPIO.add_event_detect(C4, GPIO.RISING, callback=keypadCallback)
def setAllLines(state):
GPIO.output(L1, state)
GPIO.output(L2, state)
GPIO.output(L3, state)
GPIO.output(L4, state)
def checkSpecialKeys():
global input
pressed = False
GPIO.output(L3, GPIO.HIGH)
if (GPIO.input(C4) == 1):
print("Input reset!");
pressed = True
GPIO.output(L3, GPIO.LOW)
GPIO.output(L1, GPIO.HIGH)
if (not pressed and GPIO.input(C4) == 1):
if input == secretCode:
print("Code correct!")
# TODO: Unlock a door, turn a light on, etc.
else:
print("Incorrect code!")
pressed = True
GPIO.output(L3, GPIO.LOW)
if pressed:
input = ""
return pressed
def readLine(line, characters):
global input
# We have to send a pulse on each line to
# detect button presses
GPIO.output(line, GPIO.HIGH)
if(GPIO.input(C1) == 1):
input = input + characters[0]
if(GPIO.input(C2) == 1):
input = input + characters[1]
if(GPIO.input(C3) == 1):
input = input + characters[2]
if(GPIO.input(C4) == 1):
input = input + characters[3]
GPIO.output(line, GPIO.LOW)
try:
while True:
if keypadPressed != -1:
setAllLines(GPIO.HIGH)
if GPIO.input(keypadPressed) == 0:
keypadPressed = -1
else:
time.sleep(0.1)
else:
if not checkSpecialKeys():
readLine(L1, ["1","2","3","A"])
readLine(L2, ["4","5","6","B"])
readLine(L3, ["7","8","9","C"])
readLine(L4, ["*","0","#","D"])
time.sleep(0.1)
else:
time.sleep(0.1)
except KeyboardInterrupt:
print("\nApplication stopped!")
You may have noticed that the "while" loop we used above is polling for each row of our Keypad. This is OK for a basic project, but it may not function properly if your project requires interaction with a more complex system i.e. robotics.
The other option is to utilize a library that relies on "interrupts," allowing us to assign a different event controller to each key on our Keypad. The Pi 4 would be alerted(interrupted) by a click on the membrane switch.
The following code will walk you through the process step by step. You can see that the code that iteratively scans each row no longer uses polling while loop. You will receive feedback whenever the button is pressed or released by pressing the number one on your Keypad.
import RPi.GPIO as GPIO
import time
def event_callback(pin):
value = GPIO.input(pin)
print(f"pin :: {pin}, value is {value}")
if __name__ == '__main__':
button_pin = 23
row_pin = 17
GPIO.setmode(GPIO.BCM)
GPIO.setwarnings(False)
GPIO.setup(row_pin, GPIO.OUT)
GPIO.setup(button_pin, GPIO.IN, pull_up_down = GPIO.PUD_UP)
GPIO.output(row_pin, GPIO.LOW)
# events can be GPIO.RISING, GPIO.FALLING, or GPIO.BOTH
GPIO.add_event_detect(button_pin, GPIO.BOTH,
callback=event_callback,
bouncetime=300)
try:
time.sleep(1000)
except KeyboardInterrupt:
GPIO.cleanup()
Please enter the following into your terminal to execute this code. When I press the switch, its value drops to zero, and when I let go of it, it jumps to one.
With this knowledge in hand, I searched for a library that provides a similar capability. I came across pad4pi in the pypi repository, which does the trick—type in the following command to set it up on your Raspberry Pi.
pip install pad4pi
This is the test script I eventually came up with afterward. Check out the source and sample test scripts on the library's main page.
#!/usr/bin/python
from pad4pi import rpi_gpio
import time
KEYPAD = [
[1, 2, 3, "A"],
[4, 5, 6, "B"],
[7, 8, 9, "C"],
["*", 0, "#", "D"]
]
ROW_PINS = [17, 27, 22, 5] # BCM numbering
COL_PINS = [23, 24, 25, 16] # BCM numbering
def print_key(key):
print(f"Received key from interrupt:: {key}")
try:
factory = rpi_gpio.KeypadFactory()
keypad = factory.create_keypad(keypad=KEYPAD,row_pins=ROW_PINS, col_pins=COL_PINS) # makes assumptions about keypad layout and GPIO pin numbers
Keypad.registerKeyPressHandler(print_key)
print("Press buttons on your keypad. Ctrl+C to exit.")
while True:
time.sleep(1)
except KeyboardInterrupt:
print("Goodbye")
finally:
keypad.cleanup()
Import required modules on lines 3 and 4.
GPIO pins and rows are defined on lines 6-14.
A toggle activates the callback feature on the Keypad, located at lines 16–18.
Initialization script for pad4pi and callback handler registration lines 19–31.
Here is the output of this program.
The hardware diagrams call for almost no more parts, and the firmware is based on a straightforward technique that any newbie can quickly grasp. Pay attention to these two details, if you really care about giving people a pleasant time while using the Keypad. These images demonstrate the use of a capacitor for debouncing in hardware.
The extra pulse that a button may send to the controller but it is already released, is one of the most typical problems with a mechanical keypad. The button's spring mechanism is responsible for this behavior. As a result, it's common for the firmware to save conflicting settings for the same button. Debouncing is used to prevent the Keypad from being read incorrectly. This can be accomplished mechanically by installing a capacitor to block the after-button-release micro pulses.
Firmware writers can opt to use software debouncing as well. The firmware now filters out the infinitesimally brief pulses from samples that can never be activated by human contact instead of examining each individual triggering input. It's also useful for keeping the Keypad traces free of noisy signals that could couple through the background electricity. To avoid such problems, correct design principles must be established.
This article has shown how a basic 4x4 keypad can be connected to Raspberry Pi 4 to give users a quick and easy way to enter data and communicate with their own Raspberry Pi-based applications. A small number of digital I/O pins can power the Keypad. Since the key matrix only comprises push buttons, the Raspberry Pi is not required to provide power to the device.
Every Keypad's internal matrix row receives pulses from the Raspberry Pi 4. When a user presses a button, it closes a contact that links a specific row to a particular column. To determine which key the user has pressed, the Raspberry Pi monitors the column signals and responds accordingly. Any language compatible with a Pi 4 can accomplish this method.
So, that was all for today. In the next tutorial, we will discuss How to get a PWM Singal in Raspberry Pi 4. Stay tuned!!!
Data-driven design is a powerful tool that can help you create an effective product. By leveraging data to inform your decisions, you can ensure that the design of your product will be tailored to meet user needs and preferences. This in turn leads to increased engagement and satisfaction among users, as well as more successful products overall. In this article, we'll look at how to use data to inform your product design decisions – from understanding your data sources and analyzing user behavior & feedback all the way through refining the design based on feedback and results. With these tips in hand, you'll be well-equipped to create a successful product with a great user experience.
Comprehend Your Information Sources
Have you at any point thought about how organizations foster items that impeccably take care of their client's requirements? The response lies in using the information to illuminate item design choices. Nonetheless, it's critical to comprehend that not all information is made equivalent. Prior to pursuing any choices, ensure you have a reasonable comprehension of what information sources you're utilizing and the way that solid they are. Crude information can be overpowering, so carve out an opportunity to filter through it and distinguish examples or patterns that will assist you with making an item that your clients will cherish. By involving information as your compass, you'll have the option to settle on informed choices that will prompt items that genuinely resound with your ideal interest group.
Each incredible item begins with a thought, however having a thought isn't sufficient to make your item a triumph. The way to build an incredible item is to stand by listening to your clients, figure out their way of behaving, and consider their input. This is where information comes in. By dissecting client conduct and criticism, you can acquire experiences into what your clients truly need and need, which will illuminate your item design choices. With the right devices and mentality, you can make an item that addresses client issues as well as surpasses them. Thus, don't neglect the significance of information in your item design process, it very well may be the way to your next huge achievement!
The universe of item design is continually advancing and to remain significant, it is fundamental you stay aware of the evolving patterns. Quite possibly the best method for doing this is by utilizing information to illuminate your design choices. By examining client conduct, overviews, and criticism, you can distinguish areas of progress in your item that you can address. For example, you might see that clients are continually grumbling about the convenience of your website, and by utilizing information to illuminate your direction, you can make designated upgrades to improve the client experience. Along these lines, if you need to make items that are engaging as well as successful, begin utilizing information to illuminate your design choices today.
Information can be a staggeringly incredible asset for item design choices, yet it means a lot to know how to decipher and utilize it for your potential benefit appropriately. One successful technique is through A/B testing, where you contrast two variants of a design and a select gathering of clients to see which one performs better. This permits you to approve changes and settle on informed choices in light of genuine client conduct, as opposed to simply speculating or depending on convictions. Also, it can save time and assets by keeping away from expensive confuses and improving your item with the greatest effect. In this way, if you need to take your design methodology to a higher level, think about utilizing the force of information and A/B testing to settle on your choices more information-driven and powerful. If you need help with executing A/B testing or designing feasible thing pages, contact a SaaS web design agency to get everything going.
Information can be your vital aspect for opening effective item design choices, yet it means a lot to know how to appropriately utilize it. One pivotal step is to foster a model and test it out on genuine clients. This not only proves whether or not your design is effective but also provides real-world feedback from those who will actually use the product. It's like trying on clothes before buying them - you want to make sure they fit and feel comfortable before committing to a purchase. By utilizing data and testing your prototype, you can confidently make informed decisions about the final design of your product. Don't let guesswork be your guide - let the data lead the way.
Data. It's everywhere. But how do you use it to make informed decisions about your product design? The key is to rely on feedback and results. Don't just throw your design out into the world and hope for the best. Take the time to:
gather feedback
analyze the results
refine your product based on what you learn.
Thusly, you'll have the option to make an item that addresses the issues of your clients as well as surpasses their assumptions. So make sure to plunge carelessly into the universe of information. Allow it to direct you toward progress.
Item design is a complicated cycle that requires a comprehension of client needs and the capacity to really utilize information. By utilizing the force of information, you can illuminate your choices and make items that meet client assumptions while likewise surpassing them. Through A/B testing, prototyping, input investigation, and results following, you can refine your item founded on true experiences from clients who will really be utilizing it. Data should be at the center of every successful product design strategy - so don't overlook its importance! With these tips in mind, you'll be sure to develop a winning solution for your customers.
Cryptocurrency trading is a popular way to get started with cryptocurrency. It's also a great way to multiply your funds if you're an experienced trader. In this post, we'll give you the basics of how cryptocurrency exchanges work and help you choose an exchange.
Cryptocurrency trading is the process of buying and selling cryptocurrency on an exchange. Cryptocurrencies are digital assets that can be exchanged for other cryptocurrencies, for example, you can exchange eth for sol
, or for fiat currency (US dollars).
You can use a cryptocurrency exchange to trade your coins, or you can buy them directly from another person. Some exchanges offer both options: they allow users who want to trade coins with one another and also serve as platforms where people buy and sell their coins with each other through the site's interface. Exchanges work like stock markets but instead of stocks being traded, it's digital currencies such as Bitcoin that get exchanged back and forth between traders using their funds from bank accounts or credit cards on file with these sites' payment processors like PayPal or Stripe.
A cryptocurrency exchange is a type of online platform where you can buy, sell, and trade cryptocurrencies. These exchanges act as intermediaries between buyers and sellers, allowing them to trade with each other at an agreed-upon price. The most popular ones are those that support fiat currencies like USD or EUR (the euro), but some also allow you to trade using other cryptocurrencies like bitcoin.
Cryptocurrency exchanges work similarly to stock exchanges: You place your order with one person who's willing to sell their coins at the price you're asking for, then someone else comes along with enough money in hand for them both, and voila! You've just made yourself some money by selling your coins on the market. Just like stock markets have different rules depending on where they're located (for example Japanese stocks tend not to be traded outside Japan), so too do cryptocurrency markets differ from country to country based on local regulations regarding trading platforms such as these here in Europe versus those located elsewhere around the world such as China's YuBigChina Exchange which recently launched its coin called YBC Coin which aims specifically towards Chinese citizens looking into investing but don't necessarily know how yet because there aren't many educational resources available locally yet either.
If you're new to cryptocurrency trading, it can be difficult to know where to begin. The first thing that you need to do is choose an exchange. There are many different exchanges out there and they all offer different features, so you must choose one that meets your needs.
Some things to look for when choosing a cryptocurrency exchange:
Reputation - before signing up with an exchange, look at its reputation, read reviews from other users who have traded on that platform, and you can also check if it is legal.
Security features - some exchanges require users' personal information before allowing them to access their accounts. And some exchanges don't require any personal information at all!
Available cryptocurrencies - Look carefully, because some services may only allow certain cryptocurrencies, while others may offer more options.
But the more options a company offers, the higher the transaction fees can be.
As with any investment, it's important to do your research and choose an exchange that is well-known and trusted. You should also be aware of the risks that may arise when trading cryptocurrencies. One of the most common mistakes people make when first getting started is investing more than they can afford to lose, so make sure you have a budget set aside for this activity before committing any funds.
We hope that this guide has helped you understand the basics of cryptocurrency trading on exchanges. If you want to learn more about trading, we recommend checking out our other articles on this topic!
Data science is a rapidly growing field that is revolutionizing the way businesses and organizations operate. With the explosion of data in recent years, there is a high demand for professionals who can analyze, interpret, and make decisions based on large amounts of complex data. Pursuing a degree in data science can provide you with a variety of benefits, including high-demand job opportunities, diverse skill sets, strong problem-solving skills, interdisciplinary learning, and the ability to innovate. Some of the key benefits are explained below.
Obtaining a degree in data science is a smart career move, especially considering the high demand for qualified professionals in this rapidly growing industry. One of the most significant benefits of obtaining a degree in data science, whether online or on campus, is the increasing demand for professionals in this field. As businesses continue to generate and store vast amounts of data, there is a growing need for individuals who can analyze and interpret this data to inform decision-making.
The field of data science encompasses roles such as data scientists, data analysts, machine learning engineers, and more. All of these careers are in high demand in industries such as finance, healthcare, marketing, and more. Pursuing a bachelor of data science online can provide additional benefits, such as flexibility and convenience. Online programs allow students to access course materials and complete assignments at their own pace, making it easier to balance their studies with work, family obligations, and other commitments. Additionally, online programs can be more cost-effective than traditional on-campus programs, as they typically eliminate the need for transportation costs, room and board, and other expenses associated with attending an on-campus program.
Another significant benefit of obtaining a degree in data science is the diverse skillset that you will acquire throughout the program. Working with large amounts of data requires a wide range of skills, including programming, statistical analysis, data mining, machine learning, and more. Pursuing a degree in Data Science will allow you to develop proficiency in these essential areas, and you will learn how to use various tools and techniques to analyze data and extract insights.
Programming skills are fundamental to data science as they enable you to manipulate, clean, and transform data efficiently. You will also get to know how to code in languages such as Python, R, and SQL and how to use various libraries and frameworks to analyze and visualize data.
Statistical analysis is another critical area in data science that you will learn. You will gain expertise in probability theory, hypothesis testing, regression analysis, and more. These skills are necessary to interpret and draw insights from complex data sets.
A data science degree is a program that offers students an interdisciplinary learning experience. This field of study involves the use of data to derive insights and make informed decisions. To be successful in this field, individuals need to know various disciplines, including mathematics, computer science, and business.
As you pursue a Data Science degree, you will gain a comprehensive understanding of these fields, which will enable you to work effectively with professionals from diverse backgrounds. You will also learn to apply critical thinking skills to solve complex problems that require a multidisciplinary approach.
The interdisciplinary approach to learning in data science can also help you identify new opportunities for innovation and collaboration. By combining knowledge and skills from different fields, you can create new solutions that address challenges more effectively and efficiently.
A data science degree is a program that equips students with the ability to innovate. Data science is a dynamic and rapidly evolving field where new tools and techniques are constantly emerging. By pursuing a Data Science degree, you will develop the necessary knowledge and skills to stay current with the latest developments in the field.
This knowledge will enable you to innovate and bring new ideas to the table. In today's fast-paced business environment, the ability to innovate is critical. With a Data Science degree, you can leverage the latest technologies and techniques to solve complex problems and identify new opportunities.
Moreover, the skills you acquire during your degree will enable you to develop new solutions that improve business processes and decision-making. You will be able to analyze large volumes of data and extract valuable insights that can inform business strategies.
Innovative thinking is a crucial skill that is highly valued in the field of data science. Pursuing a degree in data science provides you with a deep understanding of various data-related concepts, techniques, and tools. This knowledge, coupled with your creativity and problem-solving abilities, enables you to develop innovative solutions to complex problems.
In data science, innovative thinking involves identifying patterns, trends, and insights others may not have noticed. You can use this information to develop new approaches to solving problems, improve existing processes, and create new products or services.
By combining data analysis with innovative thinking, you can discover new opportunities that may have been previously overlooked. For instance, you may identify potential new markets, discover patterns in customer behavior, or find new ways to improve efficiency in operations.
Innovation is vital in today's rapidly changing business landscape, and a Data Science degree equips you with the skills and knowledge necessary to stay ahead of the curve. It allows you to think outside the box, generate fresh ideas, and develop solutions that can set you apart in the job market. Ultimately, pursuing a degree in data science can help you cultivate the innovative thinking skills necessary to succeed in this dynamic field.
In conclusion, obtaining a degree in data science offers several benefits. The field of data science is in high demand, with organizations seeking professionals who can extract insights from large and complex datasets. Data science also requires a diverse skillset, including programming, statistics, machine learning, and data visualization. This makes it an interdisciplinary field where individuals with backgrounds in various fields can contribute to solving complex problems.
Data science also requires a strong problem-solving ability, which is highly valued in many industries. Individuals trained in data science can develop a unique perspective on problem-solving focused on leveraging data to drive informed decisions.
The choice of operating system for a virtual private server depends on the needs of a particular company. But if you are looking for a reliable, efficient, and flexible solution to host your web projects, in most cases it will be Windows VPS. In this article, we'll analyze why many people prefer Microsoft solutions, and what benefits and limitations you can expect if you decide to buy a Windows VPS .
Windows VPS is a virtual private server that uses Windows Server as the underlying operating system. Windows VPS functions effectively as a cloud server with elastic scalability. This means that you get a dedicated server resource that you can use as you see fit, and you can easily add resources as needed.
Typically, a private server under Windows is used in many segments, it can be hosting websites and applications, databases, mail servers, and game servers. The main advantage is that the system allows you to run programs and scripts that require a Windows-compatible environment. For example, you can use Windows VPS for hosting ASP.NET, .NET Core, SQL Server, and other Microsoft technologies.
The main reason Windows VPS is preferred is that the system is developed by the largest player on the market. Microsoft is a multi-billion dollar company that invests huge budgets in its products. Other vendors do not have the same amount of resources, it is difficult for them to compete at this level. Consider the other advantages of using a Windows VPS.
Windows VPS requires no additional configuration or software installation. You can start working with it immediately after purchase and get full control over the server. You can choose the desired version of Windows Server (from 2008 to 2022), that best suits your needs and requirements.
But most importantly, the user gets access to a remote desktop with an intuitive graphical interface. There is no need to program anything from the command line, as is required in UNIX-based systems.
The system easily integrates with other Microsoft services such as Office 365, Azure, and SharePoint. You can install additional Windows software such as IIS, Active Directory, and Exchange Server.
You get a single, seamless software interface where you can use cloud services from Microsoft for data storage, analytics, machine learning, and other purposes. It is possible to synchronize the server with other Windows devices and applications, such as Outlook, OneDrive, and Skype.
Microsoft understands what customers want and for 20 years Windows Server developers have eradicated almost all the technical problems associated with the product.
With VPS on Windows Server, you don't have to wait long for vulnerabilities to be fixed. The company promptly and regularly releases security updates and patches, which are installed automatically. With open-source systems, you achieve the same result only if the product has an extensive community.
Windows VPS is ideal for developing and hosting web applications based on ASP and ASP.Net Core – popular technologies from Microsoft. You can use different programming languages like C#, VB.Net, and Python and connect different databases: SQL Server, MySQL, Oracle, and others.
Windows Server is a great software for hosting and other tasks, but not perfect. The system has some limitations which may be critical for a certain group of users.
The first is the high cost. One of the main disadvantages is that Windows VPS is usually more expensive than Linux VPS or shared hosting. This is because VPS requires an additional license for Windows Server, and it is included in the cost of renting a server. Add to this the fact that most tools and software are paid Microsoft products, and using a Windows VPS will put a noticeable strain on your budget.
But note that the high cost is a relative indicator. You can almost always find free alternatives to Microsoft programs. And due to the stable operation of the server and quality support in the long run, you can save thousands of dollars. Windows servers are much less likely to crash and are easier to resume operation than other operating systems.
Another disadvantage of using a Windows VPS is problems with performance and compatibility. You may encounter conflicts between different versions of Windows Server or between the OS from Microsoft and other operating systems. For example, it is possible to have problems when running Windows Server 2022 on old hardware, or when trying to connect to a Windows VPS from a Linux computer.
But if you rent a VPS server, such cases will be rare. Most likely, the hosting company has already taken care of installing modern performance equipment and configuring compatibility settings.
Some programs or scripts may run better on a Linux VPS than on a Windows VPS since they were originally designed for a Linux-compatible environment. For example, you may have problems running PHP or MySQL on a Windows VPS, since these technologies are optimized to run on Linux. Windows VPS is not suitable for developing and running web applications in Ruby on Rails or Node.js, as these technologies work better on Linux VPS.
Among many users, there is an opinion that Linux VPS is preferable in terms of security, and there is a logic in that. The dominance of Windows on the desktop market has made Microsoft systems a prime target for hackers. But Windows has a lot of tools to protect your server from hackers.
You can protect your data from unauthorized access or loss through a variety of security measures, such as
Firewalls. Allow you to control incoming and outgoing network traffic and block unwanted or dangerous connections. You can use both the built-in Windows Firewall and third-party tools, such as Bitdefender or Norton, to protect your Windows VPS from hackers, viruses, or other attacks.
Intrusion detection and prevention systems (IDS/IPS). These are programs or devices that analyze network traffic and detect and prevent hacking attempts or other anomalous activities. You can use IDS/IPS at the operating system level or at the application level.
Data encryption and SSL certificates. You can use BitLocker or VeraCrypt to encrypt disk space or Let's Encrypt and Comodo to obtain SSL certificates.
Of course, Windows VPS allows you to create real-time backups and regularly scheduled backups.
Windows VPS can be a suitable solution for your projects if you want:
run programs or scripts that require a Windows-compatible environment;
have full control over your server and configure it as you wish;
get high performance and reliability of the server.
Windows VPS provides flexibility and scalability, data security, and ease of management for web projects. However, Windows VPS has some limitations. Therefore, you must carefully choose Windows VPS for your projects, first of all, based on usage scenarios. You should also consider other parameters such as server resources, Windows Server version, and purchase or lease costs.
Welcome to the next tutorial of our raspberry pi 4 programming course. A previous article covered connecting a Remote Control Radio Frequency Module (433 MHz) to a Raspberry Pi 4. To turn things on and off wirelessly, we programmed a Raspberry Pi 4 to act as a radio-frequency (RF) remote control. However, this guide will study how to wirelessly pair a Raspberry Pi 4 and an ESP32. After reading this article, you'll get a good grounding in the fundamentals of Bluetooth module operation between two ESP32 and Pi 4 communication.
When it comes to sharing data over short distances using Ultra High-Frequency Radio Waves, Bluetooth is one of the most reliable and effective short-range wireless communication solutions. Since Bluetooth Technology was initially conceived as a cable substitution technology, its implementation in embedded devices is inevitable. While popular microcontrollers like the ESP32, Raspberry Pi, and Arduino Mega all come equipped with Bluetooth modules by default, others can be made Bluetooth-ready by adding modules like the HC 05 or JDY-30.
You will require the following things:
Raspberry Pi
Arduino IDE
Two ESP32 Development Boards*
NRF Application
USB Cable for ESP32
PyQt is binding for the Qt C++ libraries & development tools that allow for the creation of GUIs independent of the underlying platform (GUIs). Other robust technologies accessed through Qt include networking, threading, regex, Database queries, SVG, OpenGL, and XML.
Since PyQt6 is the library's future, it will be used in this lesson. All references to PyQt from this point forward should be taken to mean PyQt6. Based on Qt v6, PyQt6 is an implementation of Qt. As such, it offers classes and utilities for working with graphical user interfaces, XML, networking, regex, threads, Database queries, and the web, among other technologies supported by Qt. Many of the Qt classes' bindings have been implemented in a set of Modules that make up the PyQt6 package at the Python level. If you're using Python 3.6.1 or later, you can install PyQt6.
In addition to Windows and Linux, PyQt6 works on mac, Android, and Android. This is appealing if you need a Graphical framework to create cross-platform apps that look and feel natural on all of them.
There are PyQt6 binary packages available in the repositories of several Linux systems. If this describes your situation, the library can be installed through your distribution package manager. For instance, this is a command you can use on Ubuntu:
sudo apt install python3-pyqt6
This command will set up your system so you can utilize the PyQt6 library in any GUI applications you undertake. It's important to remember that you need root access to perform this; thus, the sudo command will be used.
Raspberry Pi and ESP32 are the only microcontrollers that ship with Bluetooth Low-Energy Technology modules. While traditional Bluetooth is optimized for data transfers over long distances and wide bandwidths, BLE is optimized for short-range and low-power usage. As a result of its superior efficiency in conserving energy, it consumes less power than traditional Bluetooth by a factor of over one hundred, with just a negligible drop in performance. Unlike traditional Bluetooth, which stays on even when not in use, BLE goes into a sleep state whenever it is not actively involved in a connection or data transfer.
It can function in one of four ways:
A peripheral device publicizes data and facilitates communication with other, further-flung gadgets.
A broadcaster is a gadget explicitly designed to disseminate information.
Observer - Data-only monitoring hardware.
A central device serves a dual purpose: scan for and connect to other devices.
Before the introduction of BLE, the first two modes were used by detectors and other industrial machinery, while personal computers and mobile phones used the latter two modes. Most BLE, however, now supports all four transfer methods thanks to technological advances. These transfer methods are available on the ESP32 and the Raspberry Pi. In the table below, you can observe the vast distinction between the traditional and BLE.
The ESP32 is a new System-on-a-Chip (SoC) microcontroller by Espressif Systems, the company responsible for the widely used ESP8266 SoC. For those looking for a 32-bit alternative to the ESP8266 SoC, Tensilica has you covered with their Xtensa LX6 Microprocessor, which comes in single-core and dual-core flavours and boasts built-in WiFi and Bluetooth.
A power amplifier, a low-noise reception amplifier, an antenna-selection switch, filters, and a balun for regulating the signal intensity are all included on the ESP32, just as they are on the ESP8266. Since the ESP32 requires so few external components, hardware development is streamlined.
The ESP32 is produced with TSMC's ultra-low-power 40 nm technology, another essential feature to keep in mind. As a result, employing ESP32 for the development of battery-operated applications like smartwatches, fitness trackers, baby monitors, and other similar devices should be a breeze.
If high-quality hardware like ESP32 can be programmed (coded) in multiple ways, it will be more accessible to a broader audience. As may be expected, the ESP32 is compatible with various development environments.
These are only a few examples of widely-used IDEs (integrated development environments):
Arduino IDE
PlatformIO IDE (VS Code)
LUA
MicroPython
Espressif IDF (IoT Development Framework)
JavaScript
Because of how comfortable it is, we'll be using the Arduino IDE to code the ESP32 we'll use in future projects. Other options are available to you as well.
Using the ESP32 DevKit Board as an example, we can examine its design to learn about the components that typically make up an ESP32 Development Board.
In the accompanying picture, you can see how the ESP32 Development Board I own is laid out.
Note: The market is flooded with ESP32 Boards that use the ESP-WROOM-32 Module. Different boards have different designs, pinouts, and sets of features.
The pin count on my board is 30. Some boards have 36 pins, while others have somewhat fewer. Therefore, before making any connections or turning on the board, you should verify that the pins are in the correct positions.
Depicted in the illustration are the components that make up the ESP32 Board:
ESP-WROOM-32 Module
Two rows of IO Pins (with 15 pins on each side)
CP2012 USB – UART Bridge IC
Micro–USB Connector (for power and programming)
AMS1117 3.3V Regulator IC
Enable Button (for Reset)
Boot Button (for flashing)
Power LED (Red)
User LED (Blue – connected to GPIO2)
Some passive components
The DTR and RTS pins on the USB-to-UART IC are utilized to automatically put the ESP32 into programming mode (when necessary) and to put the board to sleep after programming.
A specialized ESP32 Pinout guide is something I intend to create. Meanwhile, check out the ESP32 Development Board's wiring diagram.
ESP Boards with 30 pins are supported with this pinout. Both the 30-pin and 36-pin versions of the ESP Board's pinout will be covered in this tutorial.
Now that you have a basic understanding of ESP32, it's time to see how it can be used. There is only so much more I can add to this chapter than what's already been said. The many sections of this guide should have stimulated some thought processes in your head. You probably already have an essential list of uses for ESP32 written out. Furthermore, most of your suggested services are doable.
Although ESP32 is a viable option for many uses, it is better suited for some. In this chapter, I'll explain the criteria you should use to decide whether or not to use ESP32 in a given application. This chapter is geared at production, so if you're thinking of hundreds or even thousands of devices, you're probably looking in the wrong place. If you only need to connect a few devices and ESP32 has what you need, utilize it without hesitation. You can confidently use ESP32 for prototyping and Proof of Concept (PoC).
ESP32's built-in support for wireless networking is a strong selling point. Thus, the ESP32 is the ideal microcontroller for a stationary application where reliable WiFi connectivity is not a primary concern, such as a lab-based environmental monitoring system. You won't need to buy a separate networking module because the WiFi stack is built right into the Module. If you plan on using the ESP32 in a mobile asset tracking application, however, you'll need a GSM or LTE module to maintain a constant connection to the server. As a result, ESP32 loses its cost advantage, and you may be better suited with a less expensive microcontroller that can still accomplish your goals.
Furthermore, ESP32's built-in hardware encryption accelerator makes it an excellent choice for any project that needs to communicate securely (HTTPS). Therefore, if you need to protect sensitive data from being intercepted, using an ESP32 microcontroller is preferable to using one of the many others that don't have this feature. The military industry is one possible use case for Industrial IoT.
Due to its dual-core architecture, the ESP32 is an excellent choice for data-intensive applications like those that require processing and transmission of data to occur on separate cores, as is the case with receiving information at a high baud rate. Industrial IoT is home to several such implementations. A microcontroller with less impressive specifications may be better suited for an actual application in which a secure connection isn't even necessary. So why bother with two cores if you can get by with only one?
The available GPIOs and peripherals are another consideration. There are three Universal Asynchronous Receiver/Transmitter (UART) channels on an ESP32. You may need to choose a different microcontroller if your application requires more than three UART channels. Similarly, the ESP32's 34 programmable GPIOs are plenty for most uses. However, if more general-purpose input/output (GPIO) pins are needed for your application, you may need to look at a different microcontroller.
With 1.5 MB of SPIFFS by default, the ESP32 offers more excellent onboard storage than competing microcontrollers. ESP32 eliminates the need for an additional Flash Chip or SD Card if your data storage needs are under 1.5 MB. As a bonus, the ESP32 handles wear-levelling within SPIFFS on its own. Nonetheless, the ESP32's competitive edge is nullified once more if it doesn't satisfy your data storage needs.
The 520 KiloByte of RAM on an ESP32 is likewise plenty of space for the vast majority of uses. This only becomes a stumbling block for resource-intensive tasks like image/video processing.
Using the ESP32's built-in Bluetooth Low Energy (BLE) functionality, two microcontrollers may establish a highly efficient wireless link. With a Bluetooth connection between the two boards, one will take on the server role, while the other will take on the client role. For this project, one ESP32 will function as the server, broadcasting the data and establishing the connection, while the other ESP32 will take on the client's part, receiving the data broadcast by the server. Over the BLE connection, we will be exchanging strings between two esp32s.
The first ESP32 we build will serve as a Bluetooth host. To the client, it will supply the link and the information. Here is its source code:
#include "bleutils.h"
#include "bleserver.h"
#define SERVICE_UUID "4fafc201-1fb5-459e-8fcc-c5c9c331914b"
#define CHARACTERISTIC_UUID "beb5483e-36e1-4688-b7f5-ea07361b26a8"
void setup() {
Serial.begin(115200);
Serial.println("Starting BLE work!");
BLEDevice::init("ESP32 AS A BLE");
BLEServer *pServer = BLEDevice::createServer();
BLEService *pService = pServer->createService(SERVICE_UUID);
BLECharacteristic *pCharacteristic = pService->createCharacteristic(
CHARACTERISTIC_UUID,
BLECharacteristic::PROPERTY_READ |
BLECharacteristic::PROPERTY_WRITE
);
pCharacteristic->setValue("Hi,other ESP32 here is your data");
pService->start();
// BLEAdvertising *pAdvertising = pServer->getAdvertising(); // this still is working for backward compatibility
BLEAdvertising *pAdvertising = BLEDevice::getAdvertising();
pAdvertising->addServiceUUID(SERVICE_UUID);
pAdvertising->setScanResponse(true);
pAdvertising->setMinPreferred(0x06);
pAdvertising->setMinPreferred(0x12);
BLEDevice::startAdvertising();
Serial.println("Characteristic defined!");
}
void loop() {
// put your main code here to run repeatedly:
delay(2000);
}
Code objects such as characteristics, BLE objects, and Advertising objects are all created using the BLE class. It begins with a Characteristic UUID and a Service UUID. The Universally Unique Identifier (UUID) is a string of bytes that can specify a Bluetooth device's features and capabilities. First, we initialized three objects of the BLEserver, BLE characteristic, and BLEService classes with the necessary data. Then, after setting up our Bluetooth server's UUID, attributes, and Services, we started it using the BLE device class's start advertising function. Any information, from sensor readings to business metrics, can be pre-set and advertised. Following the activation of this server, nRF Connect can be used to gain access to it from any mobile device.
Once you've established a connection with your ESP32, inspect the feature and see your text displayed.
The second esp32 will function as a client, requesting information from the host device. The only information needed to establish a connection to the server esp32 and use its given services is the UUIDs of those services and the characteristics they identify.
Its program is as follows:
#include "BLEDevice.h"
//#include "BLEScan.h"
// The remote service we wish to connect to.
static BLEUUID serviceUUID("4fafc201-1fb5-459e-8fcc-c5c9c331914b");
// The Characteristic of the remote service we are interested in.
static BLEUUID charUUID("beb5483e-36e1-4688-b7f5-ea07361b26a8");
static boolean doConnect = false;
static boolean connected = false;
static boolean doScan = false;
static BLERemoteCharacteristic* pRemoteCharacteristic;
static BLEAdvertisedDevice* myDevice;
static void notifyCallback(
BLERemoteCharacteristic* pBLERemoteCharacteristic,
uint8_t* pData,
size_t length,
bool isNotify) {
Serial.print("Notify callback for characteristic ");
Serial.print(pBLERemoteCharacteristic->getUUID().toString().c_str());
Serial.print(" of data length ");
Serial.println(length);
Serial.print("data: ");
Serial.println((char*)pData);
}
class MyClientCallback : public BLEClientCallbacks {
void onConnect(BLEClient* pclient) {
}
void onDisconnect(BLEClient* pclient) {
connected = false;
Serial.println("onDisconnect");
}
};
bool connectToServer() {
Serial.print("Forming a connection to ");
Serial.println(myDevice->getAddress().toString().c_str());
BLEClient* pClient = BLEDevice::createClient();
Serial.println(" - Created client");
pClient->setClientCallbacks(new MyClientCallback());
// Connect to the remove BLE Server.
pClient->connect(myDevice); // if you pass BLEAdvertisedDevice instead of address, it will be recognized type of peer device address (public or private)
Serial.println(" - Connected to server");
// Obtain a reference to the service we are after in the remote BLE server.
BLERemoteService* pRemoteService = pClient->getService(serviceUUID);
if (pRemoteService == nullptr) {
Serial.print("Failed to find our service UUID: ");
Serial.println(serviceUUID.toString().c_str());
pClient->disconnect();
return false;
}
Serial.println(" - Found our service");
// Obtain a reference to the Characteristic in the service of the remote BLE server.
pRemoteCharacteristic = pRemoteService->getCharacteristic(charUUID);
if (pRemoteCharacteristic == nullptr) {
Serial.print("Failed to find our characteristic UUID: ");
Serial.println(charUUID.toString().c_str());
pClient->disconnect();
return false;
}
Serial.println(" - Found our characteristic");
// Read the value of the Characteristic.
if(pRemoteCharacteristic->canRead()) {
std::string value = pRemoteCharacteristic->readValue();
Serial.print("The characteristic value was: ");
Serial.println(value.c_str());
}
if(pRemoteCharacteristic->canNotify())
pRemoteCharacteristic->registerForNotify(notifyCallback);
connected = true;
return true;
}
/**
* Scan for BLE servers and find the first one that advertises the service we are looking for.
*/
class MyAdvertisedDeviceCallbacks: public BLEAdvertisedDeviceCallbacks {
/**
* Called for each advertising BLE server.
*/
void onResult(BLEAdvertisedDevice advertisedDevice) {
Serial.print("BLE Advertised Device found: ");
Serial.println(advertisedDevice.toString().c_str());
// We have found a device, let us now see if it contains the service we are looking for.
if (advertisedDevice.haveServiceUUID() && advertisedDevice.isAdvertisingService(serviceUUID)) {
BLEDevice::getScan()->stop();
myDevice = new BLEAdvertisedDevice(advertisedDevice);
doConnect = true;
doScan = true;
} // Found our server
} // onResult
}; // MyAdvertisedDeviceCallbacks
void setup() {
Serial.begin(115200);
Serial.println("Starting Arduino BLE Client application...");
BLEDevice::init("");
// Retrieve a Scanner and set the callback we want to use to be informed when we
// have detected a new device. Specify that we want active scanning and start the
// scan to run for 5 seconds.
BLEScan* pBLEScan = BLEDevice::getScan();
pBLEScan->setAdvertisedDeviceCallbacks(new MyAdvertisedDeviceCallbacks());
pBLEScan->setInterval(1349);
pBLEScan->setWindow(449);
pBLEScan->setActiveScan(true);
pBLEScan->start(5, false);
} //End of setup.
// This is the Arduino main loop function.
void loop() {
// If the flag "doConnect" is true then we have scanned for and found the desired
// BLE Server with which we wish to connect. Now we connect to it. Once we are
// connected, we set the connected flag to be true.
if (doConnect == true) {
if (connectToServer()) {
Serial.println("We are now connected to the BLE Server.");
} else {
Serial.println("We have failed to connect to the server; there is nothin more we will do.");
}
doConnect = false;
}
// If we are connected to a peer BLE Server, update the Characteristic each time we are reached
// with the current time since boot.
if (connected) {
String newValue = "Time since boot: " + String(millis()/1000);
Serial.println("Setting new characteristic value to \"" + newValue + "\"");
// Set the Characteristic's value to be the array of bytes that is a string.
pRemoteCharacteristic->writeValue(newValue.c_str(), newValue.length());
}else if(doScan){
BLEDevice::getScan()->start(0); // this is just an example of starting the scan after disconnect; most likely, there is a better way to do it in Arduino.
}
delay(1000); // Delay a second between loops.
} //End of loop
The functionality of this code depends on human input. At the outset of the code, we established the definitions of Characteristic and service UUID. Initially, BLERemoteCharacteristic and BLEAdvertisedDevice objects are created, and the connection to the server () function is used to establish a connection with the server (other esp32). In the End, it pulls in the server's data via the Characteristic and service variables. This is what these numbers will look like on the serial monitor:
To link our ESP32 to Bluetooth, we will use a UART connection. Because of this, it will have bidirectional communication with the Pi 4.
As for the program, it goes like this:
#include "bledevice.h"
#include "bleserver.h"
#include "bleutils.h"
#include "ble2902.h"
BLEServer *pServer = NULL;
BLECharacteristic * pTxCharacteristic;
bool deviceConnected = false;
bool oldDeviceConnected = false;
uint8_t txValue = 0;
// See the following for generating UUIDs:
// https://www.uuidgenerator.net/
#define SERVICE_UUID "6E400001-B5A3-F393-E0A9-E50E24DCCA9E" // UART service UUID
#define CHARACTERISTIC_UUID_RX "6E400002-B5A3-F393-E0A9-E50E24DCCA9E"
#define CHARACTERISTIC_UUID_TX "6E400003-B5A3-F393-E0A9-E50E24DCCA9E"
class MyServerCallbacks: public BLEServerCallbacks {
void onConnect(BLEServer* pServer) {
deviceConnected = true;
};
void onDisconnect(BLEServer* pServer) {
deviceConnected = false;
}
};
class MyCallbacks: public BLECharacteristicCallbacks {
void onWrite(BLECharacteristic *pCharacteristic) {
std::string rxValue = pCharacteristic->getValue();
if (rxValue.length() > 0) {
Serial.println("*********");
Serial.print("Received Value: ");
for (int i = 0; i < rxValue.length(); i++)
Serial.print(rxValue[i]);
Serial.println();
Serial.println("*********");
}
}
};
void setup() {
Serial.begin(115200);
// Create the BLE Device
BLEDevice::init("UART Service For ESP32");
// Create the BLE Server
pServer = BLEDevice::createServer();
pServer->setCallbacks(new MyServerCallbacks());
// Create the BLE Service
BLEService *pService = pServer->createService(SERVICE_UUID);
// Create a BLE Characteristic
pTxCharacteristic = pService->createCharacteristic(
CHARACTERISTIC_UUID_TX,
BLECharacteristic::PROPERTY_NOTIFY
);
pTxCharacteristic->addDescriptor(new BLE2902());
BLECharacteristic * pRxCharacteristic = pService->createCharacteristic(
CHARACTERISTIC_UUID_RX,
BLECharacteristic::PROPERTY_WRITE
);
pRxCharacteristic->setCallbacks(new MyCallbacks());
// Start the service
pService->start();
// Start advertising
pServer->getAdvertising()->start();
Serial.println("Waiting a client connection to notify...");
}
void loop() {
if (deviceConnected) {
pTxCharacteristic->setValue(&txValue, 1);
pTxCharacteristic->notify();
txValue++;
delay(10); // Bluetooth stack will go into congestion, if too many packets are sent
}
// disconnecting
if (!deviceConnected && oldDeviceConnected) {
delay(500); // give the Bluetooth stack the chance to get things ready
pServer->startAdvertising(); // restart advertising
Serial.println("start advertising");
oldDeviceConnected = deviceConnected;
}
// connecting
if (deviceConnected && !oldDeviceConnected) {
// do stuff here on connecting
oldDeviceConnected = deviceConnected;
}
}
One part of the algorithm was responsible for broadcasting a loop of completely random data. One is transmitting information, while the other is receiving it. First, we settled on RX and TX as our two distinguishing features; afterwards, we gave each of them the precise definitions and values we'd come to expect. Since we're using UART, sending and receiving data simultaneously is not a problem. Use the NRF Application to check the functionality of a single end of a connection. Open the NRF Connector app and upload the code above.
Enter the value you wish to transmit to the serial monitor after you have connected. The serial monitor will be updated with your input.
The Raspberry Pi is currently executing a Python script written in bluepy. This code creates a simple GUI for communicating with the esp. 32. The PYQT and bluepy packages need to be installed before continuing. You may run this code to see a graphical user interface as soon as everything is set up. After that, either input the information you wish to transmit to the ESP32 through BLE or view the information sent to the ESP32. It's a universal asynchronous receiver/transmitter (UART) link (universally asynchronous receiver-transmitter). Incoming info from esp32 will be displayed in the first message box, while outgoing data from Raspberry Pi can be written in the other text box.
As seen on the ESP32 serial connection display, we have the following:
import sys
import time
import requests
from PyQt5.QtCore import QObject, QRunnable, QThreadPool, QTimer, pyqtSignal, pyqtSlot
from PyQt5.QtWidgets import (
QApplication, QLabel, QMainWindow, QPlainTextEdit, QPushButton, QVBoxLayout, QWidget,
)
from bluepy import btle
class WorkerSignals(QObject):
signalMsg = pyqtSignal(str)
signalRes = pyqtSignal(str)
class MyDelegate(btle.DefaultDelegate):
def __init__(self, sgn):
btle.DefaultDelegate.__init__(self)
self.sgn = sgn
def handleNotification(self, cHandle, data):
try:
dataDecoded = data.decode()
self.sgn.signalRes.emit(dataDecoded)
except UnicodeError:
print("UnicodeError: ", data)
class WorkerBLE(QRunnable):
def __init__(self):
super().__init__()
self.signals = WorkerSignals()
self.rqsToSend = False
@pyqtSlot()
def run(self):
self.signals.signalMsg.emit("WorkerBLE start")
#---------------------------------------------
p = btle.Peripheral("3c:71:bf:0d:dd:6a")
p.setDelegate( MyDelegate(self.signals) )
svc = p.getServiceByUUID("6E400001-B5A3-F393-E0A9-E50E24DCCA9E")
self.ch_Tx = svc.getCharacteristics("6E400002-B5A3-F393-E0A9-E50E24DCCA9E")[0]
ch_Rx = svc.getCharacteristics("6E400003-B5A3-F393-E0A9-E50E24DCCA9E")[0]
setup_data = b"\x01\00"
p.writeCharacteristic(ch_Rx.valHandle+1, setup_data)
# BLE loop --------
while True:
"""
if p.waitForNotifications(1.0):
# handleNotification() was called
continue
print("Waiting...")
"""
p.waitForNotifications(1.0)
if self.rqsToSend:
self.rqsToSend = False
try:
self.ch_Tx.write(self.bytestosend, True)
except btle.BTLEException:
print("btle.BTLEException");
#---------------------------------------------hellohello
self.signals.signalMsg.emit("WorkerBLE end")
def toSendBLE(self, tosend):
self.bytestosend = bytes(tosend, 'utf-8')
self.rqsToSend = True
"""
try:
self.ch_Tx.write(bytestosend, True)
except BTLEException:
print("BTLEException");
"""
class MainWindow(QMainWindow):
def __init__(self):
super().__init__()
layout = QVBoxLayout()
buttonStartBLE = QPushButton("Start BLE")
buttonStartBLE.pressed.connect(self.startBLE)
self.console = QPlainTextEdit()
self.console.setReadOnly(True)
self.outconsole = QPlainTextEdit()
buttonSendBLE = QPushButton("Send message")
buttonSendBLE.pressed.connect(self.sendBLE)
layout.addWidget(buttonStartBLE)
layout.addWidget(self.console)
layout.addWidget(self.outconsole)
layout.addWidget(buttonSendBLE)
w = QWidget()
w.setLayout(layout)
self.setCentralWidget(w)
self.show()
self.threadpool = QThreadPool()
print(
"Multithreading with Maximum %d threads" % self.threadpool.maxThreadCount())
def startBLE(self):
self.workerBLE = WorkerBLE()
self.workerBLE.signals.signalMsg.connect(self.slotMsg)
self.workerBLE.signals.signalRes.connect(self.slotRes)
self.threadpool.start(self.workerBLE)
def sendBLE(self):
strToSend = self.outconsole.toPlainText()
self.workerBLE.toSendBLE(strToSend)
def slotMsg(self, msg):
print(msg)
def slotRes(self, res):
self.console.appendPlainText(res)
app = QApplication(sys.argv)
window = MainWindow()
app.exec()
When there isn't enough electricity to go around, BLE comes in handy. Let's talk about some of the real-world uses for it:
Intelligent Farming Methods: Battery-powered microcontrollers with ble capabilities, like the ESP32 or Raspberry Pi, can be used for weeks to relay data from sensors from one ESP32 to another to optimize plant development.
In-Game Medical Staff: Using Bluetooth, a microcontroller can transmit data to a mobile phone or show the data locally on a screen, such as a user's heart rate, running speed, or any other data detected by sensors. All of these values can be tracked effectively and with no wire required.
Biomedical Condition Tracking: The BLE capabilities of a microcontroller enables the direct transfer of data from wristbands measuring vital signs like heart rate and blood pressure to a computer.
One of the many benefits of small microcontrollers is home automation. From lighting management to fingerprint door locks, the possibilities for using BLE devices are endless. It has several fascinating uses, including:
Alarms that go off at a predetermined time to remind you to turn off the stove, water pump, heater, or geyser
Safeguarding with mobile-operated surveillance cameras
Remotely operate garage doors using a mobile device
Measurements are taken from a variety of home sensors
Using the information shown here, we successfully established a Bluetooth connection between our Pi 4 and Esp32. We learned about esp32's internals and how to use the Raspberry Pi 4 to write programs for it. In conclusion, ESP32's specifications are adequate to support the vast majority of your proposed uses. If you're looking for an upgrade from the ESP8266, the ESP32 is the next generation and supports Bluetooth 4.2 and Bluetooth Low Energy. It includes additional CPU cores, faster WiFi, more GPIO, and these technologies. In addition to having a hall effect sensor and a temperature sensor already included, the ESP32 also features touch-sensing pins that can rouse the ESP32 from a deep sleep. When increasing output, it's vital to include good specifications but not anything too fancy. To rephrase, using a less expensive microcontroller may be more cost-effective if the intended result can be achieved with more basic specifications. The cost savings become noticeable when output increases by several orders of magnitude. While it may not be the best microcontroller for mass production, the ESP32 is perfect for proof-of-concept development and prototype prototyping. Next, we'll see how to connect a 4-by-4 keypad to a Raspberry Pi 4 for electronic door locks.
Customers are becoming increasingly savvy and demanding in this ever-evolving and competitive world. Businesses need to include relevant content in all of their public interactions if they want to keep them happy and keep their business.
To be considered a complete suite, these businesses would require mobile applications, paperless forms, online communities, and other complementary applications in addition to comprehensive content management solutions for building their websites.
If this is the case, professionals will have an easier time keeping track of their content and assets and will be able to send them to the right people at the right time. The Adobe Experience Manager, is one such option, which we'll go over in detail.
As examined in the part above, Adobe Experience Director (AEM) is a substance the board arrangement that assists experts with monitoring their substance. This single platform contains everything necessary for an individual or organization to create the most crucial strategic components.
In layman's terms, AEM is a faster and easier way to give your customers access to what they want by giving them interfaces that are easy to use and built-in features. AEM Development Services has grown in both product and organization popularity due to its ease of use.
Not only does it facilitate the rapid development of mobile applications, but it also facilitates the rapid development of web applications. Utilizing AEM, associations can fabricate web applications, responsive sites, versatile applications, structures, and so forth. The ability to embed custom-built components with content fetched from its Digital Asset Manager (DAM) is one of the cool features that comes in quite handy.
For associations that are wanting to pick AEM Development Services or who are as of now utilizing them, this article ought to give practically every one of the subtleties that are expected to see better.
Not only will you be able to assist organizations in picking up the pace, but you will also gain valuable insight into the Quality Engineering roadmap as a result of this.
Adobe Experience Chief (AEM Development Services) depends on the ideas of Apache Sling, a Java application in light of OSGi utilizing the Apache Felix motor. In layman's terms, you could make reference to Apache Felix is to Apache Sling what Equinox is to Shroud IDE.
To keep storing the necessary data, Apache Sling continues to make use of an object database called the Java Content Repository (JCR), which is built with Apache Jackrabbit. Apache Sling has its own HTTP server which can be utilized as an Internet Application with an Application server (normally Breakwater). This gives the essential usefulness of a server and a servlet structure.
Apache Sling is obsolete seriously and subsequently, Adobe extended the functionalities of Sling to deliver their own improved form of Apache Sling called the Adobe CRX (Content Archive Outrageous). Starting from the start of CQ 5.4, the usefulness fundamental is moved to Rock. The majority of the underlying or low-level functionalities, such as event management, user management, and data persistence, were handled by CRX or Granite.
On top of the Granite/CRX core, the WCM/CQ features provide digital asset management and content management. When it becomes AEM, CQ is no longer the same, and it has been enhanced to such an extent that AEM is significantly more than CQ.
AEM Forms provided AEM with LiveCycle functionality, while AEM Assets provided AEM with Scene 7 functionality.
The significance of a business's online presence has increased at an exponential rate. Ongoing pandemics, like Coronavirus, have brought about huge misfortunes for firms that don't have a strong web-based presence. Additionally, customers' traditional purchasing habits have shifted from physical stores to online retailers as a result of technological advancements. Therefore, building a strong internet based presence for your business has become fundamental for drawing in new purchasers and holding existing ones.
Adobe Experience Supervisor is a well known content administration framework that helps organizations in creating sites and overseeing content and computerized resources. It is now a popular tool for businesses that want to build a strong online presence and give customers consistent, up-to-date marketing information.
The best resource for learning Adobe Experience Manager from start to finish has arrived! This Adobe Experience Manager Guide was made to help newcomers learn the basics of the CMS platform and gain a general understanding of it. At the end of this comprehensive guide to Adobe Experience Manager (AEM), you will have a comprehensive understanding of all the important topics.
Adobe Experience Manager (AEM), a comprehensive content management solution, is available from Adobe Systems. It's one of the most progressive and usually involved content administration frameworks for advanced resources and sites. Companies can simplify digital asset management with AEM's document management, social interaction, community portals, and user-generated content management capabilities.
AEM fills in as a focal workstation for imaginative groups, making everyday exercises simpler to do. It makes it possible for marketers to make, produce, and distribute marketing materials to the right people at the right time. Additionally, it provides all of the necessary strategic components on a single platform, making it possible for you to accomplish your goals.
The following are a few significant advantages of Adobe Experience Manager:
The AEM cloud network choice could assist you with overcoming any barrier between computerized resource the executives and promoting. You can keep your company's identity while streamlining operations and delivering high-quality content with the cloud integration option.
AEM gives you a distributed storage office where you might store your material and give admittance to your workers that are fanned out around the globe. The central accessing system also boosts business expansion by making work more efficient.
The AEM tool makes it easy to add tags and information to cloud-hosted files and gives you easy access to them. This approach would make future searches more creative, effective, and efficient while also eliminating the need to look for relevant content.
Adobe Experience Supervisor gives complex capacities that empower you to offer fitted substance to clients and increment brand steadfastness. You can also come up with and offer one-of-a-kind solutions that meet the needs of customers and boost the value of your brand.
You might utilize this apparatus to change over records into the arrangements you need to see to increment client commitment across various channels and stages.
The AEM solution keeps the dashboard accessible to everyone while providing distinct workspaces for each project. As a result, the architecture allows each member to be assigned a specific task. and easily collaborate with numerous groups. For example, valuable tools like annotations and comments are useful for getting feedback and making workflows better.
AEM makes it possible for customers to use the video content to advertise their goods and services on a variety of channels and platforms. Associations would profit from more prominent commitment, brand openness, and company achievement in the event that they shared smoothed out recordings consistently. You can also look at other things to get a better understanding of user behavior and make necessary changes to the content.