-
Notifications
You must be signed in to change notification settings - Fork 1
/
atom.xml
2368 lines (1829 loc) · 259 KB
/
atom.xml
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
<title type="text" xml:lang="">Electronics Club, IIT Bombay</title>
<link type="application/atom+xml" href="https://elec-club-iitb.github.io/atom.xml" rel="self"/>
<link type="text" href="https://elec-club-iitb.github.io/" rel="alternate"/>
<updated>2017-05-09T19:11:28+00:00</updated>
<id>https://elec-club-iitb.github.io/</id>
<author>
<name></name>
<email>eciitb@gmail.com</email>
</author>
<entry>
<title>Get Electrified 3</title>
<link href="https://elec-club-iitb.github.io/blog/2017/04/get-electrified-3/"/>
<updated>2017-04-24T00:00:00+00:00</updated>
<id>https://elec-club-iitb.github.io/blog/2017/04/get-electrified-3</id>
<content type="html"><p>Electronics club conducted its last electrified session on 18th March, 2017. It was totally awesome as we got an opportunity to make a half adder, full adder, subtractor and priority encoder. Along with that we also learnt some cool stuff about digital circuits.</p>
<p>##Where do we begin from to make anything as simple as an adder?</p>
<p>We basically use a combinational circuit. Not only an adder but we can even make a subtractor, priority encoder, MUX and what not!</p>
<p>Combinational circuit is basically used for making those circuits which depends on the current state.</p>
<p><img src="/assets/get-electrified-3/image_0.png" alt="Combinational Logic Circuits" /></p>
<p>##So, let us now begin with how exactly do these combinational circuits function:</p>
<h2 id="adder">Adder:</h2>
<p>As you can guess an adder simply add two numbers. But why do we need a complicated circuit to just add numbers? Actually, adders are used in the arithmetic logic units in many computers and other kinds of processors.</p>
<p>There are two kinds of adders:</p>
<h3 id="1-half-adder">1) Half adder</h3>
<h3 id="2-full-adder">2) Full adder</h3>
<p>The major difference between a half adder and a full adder is that a full-adder has three inputs and two outputs where as a half adder has only two inputs and two outputs. In a full adder, the first two inputs are A and B and the third input is an input carry.</p>
<p>The circuit diagram and truth table of a half adder and full adder is shown below:</p>
<p><img src="/assets/get-electrified-3/image_1.png" alt="Half Adder" /></p>
<p><img src="/assets/get-electrified-3/image_2.png" alt="Full Adder" /></p>
<h2 id="subtractor">Subtractor:</h2>
<p>Similarly, a subtractor subtracts two numbers. They are also of two types and as you can guess the two types are:</p>
<h3 id="1-half-subtractor">1) Half subtractor</h3>
<h3 id="2-full-subtractor">2) Full subtractor</h3>
<p>Just like in an adder, the subtractor has similar inputs just the difference is that instead of a carry we have a “borrow”.</p>
<p>The circuit diagram and truth table of a half subtractor and full subtractor is shown below:</p>
<p><img src="/assets/get-electrified-3/image_3.png" alt="Half Subtractor" /></p>
<p><img src="/assets/get-electrified-3/image_4.png" alt="Full Subtractor" /></p>
<h2 id="priority-encoder">Priority Encoder:</h2>
<p>So basically, what a priority encoder do is that it gives the highest priority of the current input as an output. So, when an input with a higher priority is present, all other inputs with a lower priority will be ignored. The priority encoder comes in many different forms with an example of an 8-input priority encoder along with its truth table shown below.</p>
<h2 id="8-to-3-bit-priority-encoder">8-to-3 Bit Priority Encoder:</h2>
<p><img src="/assets/get-electrified-3/image_5.png" alt="8 to 3 bit Priority Encoder" /></p>
<p>Where X equals “don’t care”, that is it can be either logic “0” or logic “1”.</p>
<h2 id="multiplexer-mux-and-demultiplexer">Multiplexer (MUX) and Demultiplexer:</h2>
<h2 id="how-are-multiple-signals-combined">How are multiple signals combined?</h2>
<p>MUX is used for this purpose. It has N Select lines, 2N input lines, and it routes one of the input lines to the output. Conceptually, a MUX may be thought of as 2N switches. For a given combination of the select inputs, only one of the switches closes (makes contact), and the others are open.</p>
<p>It is obvious from the name that a demultiplexer do the reverse of what a multiplexer do. It takes a single input (I) and routes it to one of the output lines. For N Select inputs, the number of output lines is 2^N.</p>
<p>Circuit diagram and truth table of a multiplexer is shown below:</p>
<p><img src="/assets/get-electrified-3/image_6.png" alt="4:1 Multiplexer" /> <img src="/assets/get-electrified-3/image_7.png" alt="Truth Table" /></p>
<p>Circuit diagram and truth table of a demultiplexer is shown below:</p>
<p><img src="/assets/get-electrified-3/image_8.png" alt="1:4 Demultiplexer" /> <img src="/assets/get-electrified-3/image_9.png" alt="Truth Table" /></p>
<h2 id="encoders-and-decoders">Encoders and Decoders:</h2>
<p>You might be wondering what is the need of an encoder?</p>
<p>It is actually used to convert information from one format to another for the purpose of standardization, speed and compressions.</p>
<p>In encoders, only one input line is assumed to be active. The binary number corresponding to the active input line appears at the output pins. The N output lines can represent 2N binary numbers, each corresponding to one of the M input lines, i.e., we can have M = 2N. Some encoders have M &lt; 2 N.</p>
<p>Similarly, you can guess the functioning of a decoder. For each input combination, only one output line is active (which means 0 or 1, depending on whether the outputs are active low or active high). Since there are 2N input combinations, there could be 2N output lines, i.e., M = 2N. However, there are decoders with M &lt; 2 N as well.</p>
<p><img src="/assets/get-electrified-3/image_10.png" alt="Encoder" /></p>
<p><img src="/assets/get-electrified-3/image_11.png" alt="Decoder" /></p>
</content>
</entry>
<entry>
<title>Improving ADCs by intentionally adding noise</title>
<link href="https://elec-club-iitb.github.io/blog/2016/10/improving-adcs-with-noise/"/>
<updated>2016-10-29T00:00:00+00:00</updated>
<id>https://elec-club-iitb.github.io/blog/2016/10/improving-adcs-with-noise</id>
<content type="html"><p>Everybody has this presumed notion that noise in an electronic system is bad.
We all learn about ways to reduce noise in the circuits we implement to get
better results. In this post we will see a case where intentionally <em>adding</em>
noise to a system will give better results.</p>
<h2 id="what-is-wrong-with-a-normal-adc">What is wrong with a normal ADC?</h2>
<p>The purpose of an Analog to Digital converter is to obtain a digital value of
an analog signal. Lets say we want to convert a signal which is between -1 to 1V.
The analog version of this signal will be a real number and so can take one
of infinitely many real values between -1 and 1. But the digital representation
will only be able to take finite number of values because we only have a finite
number of bits to encode the real number.</p>
<p>We will have to <em>quantize</em> the signal i.e. pick the closest possible
approximation of it from the set of possible values. For the sake of simplicity,
lets assume we have just 1 bit to encode the signal. So the set of values our
digital signal can take is <script type="math/tex">\{0, 1\}</script>. Now it is clear that depending on the
analog value we will have to <em>pick</em> one of 0 or 1 to represent this value as
our digital signal. The analog signal will almost never equal to -1 or 1
(try calculating the probability) so we will always get an error when we
try to <em>quantize</em> our signal. This error is called <strong>Quantization Error</strong>.</p>
<h2 id="there-is-already-an-error-and-you-want-to-add-more-noise">There is already an error and you want to add more noise?!</h2>
<p>We will eventually see that intentionally adding noise will help <em>reduce</em>
quantization error. This kind of intentionally added noise is so commonly used
that it has its own name: Dither. Dither, apart from being used in ADCs is
very widely used in image processing to display better quality images.
See an example from <a href="https://en.wikipedia.org/wiki/Dither">the wikipedia page</a>:</p>
<p><img src="//upload.wikimedia.org/wikipedia/commons/5/57/1_bit.png" alt="dithered leaf" /></p>
<p>The image of this leaf has been represented using just the colour white(1) and
black(0)! And yet it looks like it has various shades of grey! Lets see how
this happens.</p>
<h2 id="dither-in-adcs">Dither in ADCs</h2>
<p>Continuing with the quantization example above, lets say we have a 1-bit ADC
which gives output 0 if the input signal is negative and 1 if positive.
If <script type="math/tex">X</script> is the digital output and <script type="math/tex">c</script> is the analog input (assumed constant),</p>
<script type="math/tex; mode=display">% <![CDATA[
X =
\begin{cases}
\hfill 0 \hfill & \text{ if $c \leq 0$} \\
\hfill 1 \hfill & \text{ if $c > 0$} \\
\end{cases}
, c \in [-1,1] %]]></script>
<p>If we add a dither <script type="math/tex">d(t)</script> to the analog input, the value of <script type="math/tex">X</script> will be
decided by <script type="math/tex">c+d(t)</script>. Lets say we add a dither which is characterised by a
<a href="https://en.wikipedia.org/wiki/Uniform_distribution_(continuous)">uniform random variable</a>, so</p>
<script type="math/tex; mode=display">d \sim \text{U}(-\frac{1}{2},\frac{1}{2})</script>
<p>we will later see the significance of the range <script type="math/tex">-\frac{1}{2},\frac{1}{2}</script>.
Cumulative density function of <script type="math/tex">d</script> will be</p>
<script type="math/tex; mode=display">F_d(x) = x + \frac{1}{2}, x \in [-\frac{1}{2},\frac{1}{2}]</script>
<p><script type="math/tex">X</script> is dependent on a random variable, hence <script type="math/tex">X</script> will also become a random
variable. And because <script type="math/tex">X \in \{0,1\}</script> it will be a <a href="https://en.wikipedia.org/wiki/Bernoulli_distribution">Bernoulli random variable</a></p>
<p>Hence,</p>
<script type="math/tex; mode=display">X \sim \text{Ber}(p)</script>
<script type="math/tex; mode=display">% <![CDATA[
\begin{split}
P(X = 1) & = P(c+d(t) > 0) = p \\
& = P(d(t) > -c) \\
& = 1 - P(d(t) \leq -c) \\
& = 1 - F_d(-c) \\
& = F_d(c) \\
& = c + \frac{1}{2}
\end{split} %]]></script>
<p>We get <script type="math/tex">X</script> to be a be a bernoulli variable with parameter dependent on our analog
value!</p>
<script type="math/tex; mode=display">X \sim \text{Ber}(c+\frac{1}{2})</script>
<p>We can see that expected value of <script type="math/tex">X</script> is equal to <script type="math/tex">c + \frac{1}{2}</script> (because X is bernoulli).
By the law of large numbers, we can say that if we take large number of samples of
<script type="math/tex">X</script> (keeping <script type="math/tex">c</script> constant), the average value of these samples will converge
to the expected value <script type="math/tex">c + \frac{1}{2}</script></p>
<h2 id="block-diagram-for-adding-dither">Block diagram for adding dither</h2>
<p><img src="/assets/improving-adcs-with-noise/block_diag.png" alt="block diagram" /></p>
<p>The Sampler just reads the value of its input at <script type="math/tex">t = nT</script>, hence it gives
a sample at every <script type="math/tex">T</script> seconds. From our previous derivation we can say that</p>
<script type="math/tex; mode=display">\lim_{n\to\infty} \frac{1}{n}\sum_{n=0}^1 X[n] = c + \frac{1}{2}</script>
<p>The problem here is that taking an infinite number of samples will take infinite
time which is impractical. But we can say that the larger number of samples we
the better accuracy in value of <script type="math/tex">c</script> we will get.
If we take <script type="math/tex">n</script> samples, we can see that the average of <script type="math/tex">X[n]</script> will take one
of <script type="math/tex">n</script> values from the set <script type="math/tex">\{0,\frac{1}{n},\frac{2}{n},...,\frac{n}{n}\}</script>.</p>
<p>We thus have quantized <script type="math/tex">c</script> to <script type="math/tex">n</script> distinct values or <script type="math/tex">\text{log}_2(n)</script> bits
using a 1-bit ADC!</p>
<h2 id="dither-in-images">Dither in images</h2>
<p>Lets take a look at the leaf image once again. Observe that a greyscale image has
been approximated here using two distinct values (black and white) i.e. a 1-bit value.
Such an image is called a binary image.</p>
<p><img src="//upload.wikimedia.org/wikipedia/commons/5/57/1_bit.png" alt="dithered leaf" /></p>
<p>Lets say the greyscale had values for every pixel as a real number
between 0 and 1, 0 corresponding to full black and 1 corresponding to full white.
There would be regions in this image with similar values of grey. For e.g.
take the section of the top of the leaf. It is a region of light grey (value<script type="math/tex">=c>\frac{1}{2}</script>).
If we convert this region directly to binary, the whole region will become white.
Similarly we would get a large patches of black and white all over the image
which would be a pretty inaccurate depiction of the greyscale image.</p>
<p>Now if we add dither to that small region of similar greyscale value
and then convert to binary image, the probability of getting a white pixel
will be proportional to the value of that region (<script type="math/tex">=c</script>). If the region has 100
pixels, instead of all 100 being converted to white pixels, <script type="math/tex">100c</script> pixels will be
white and <script type="math/tex">100(1-c)</script> will be black. On average that will look like the region is
grey with value <script type="math/tex">c</script>.</p>
<p>We can say that the average value of a small region in the binary image will be
close to the greyscale value of that small region in the real image.
Hence we can see that dither gives us a better approximation after quantization.</p>
<p><em>Note: The leaf image is using a slightly better algorithm than just adding dither
and converting to binary (Random dithering). Such an image would look much worse, so for representative
purposes I have used this image. You can read more about better algorithms on the
wikipedia page of Dither</em></p>
</content>
</entry>
<entry>
<title>Get Electrified 2</title>
<link href="https://elec-club-iitb.github.io/blog/2016/09/get-electrified-2/"/>
<updated>2016-09-29T00:00:00+00:00</updated>
<id>https://elec-club-iitb.github.io/blog/2016/09/get-electrified-2</id>
<content type="html"><p>Greetings from Electronics Club IIT Bombay</p>
<p>We conduct Electrified sessions regularly wherein some basic electronics
concepts are discussed and some cool DIY projects based on the concepts
discussed are made.</p>
<p>On 23rd september, 2016 we conducted Electrified 2 where we discussed
Operational amplifiers, transistors, sensors, and some awesome circuits
using these devices.</p>
<p>An overview of the content we covered.</p>
<h3 id="operational-amplifiers">Operational Amplifiers</h3>
<p>Op-amp, as often called, is an extremely versatile devices which is fundamentally a
voltage amplifying device. Using opamps we can amplify, filter and do a
lot more with signals. Also in addition to that we can perform
mathematical operations such as addition, subtraction , integration and
differentiation etc.</p>
<p>For more details of Opamps you can refer our
<a href="/tutorials/basic_electronics/"><em>tutorial</em></a>
on basic electronics.</p>
<h3 id="bipolar-junction-transistors">Bipolar Junction Transistors</h3>
<p>Transistors are three terminal active devices made from different
semiconductor materials that can act as either an insulator or a
conductor by the application of a small signal voltage. The transistor’s
ability to change between these two states enables it to have two basic
functions: “switching” (digital electronics) or “amplification” (analog
electronics).</p>
<p>Enough of boring theory I guess, let’s get started with the circuits.</p>
<h2 id="projects">Projects</h2>
<h3 id="xyloband">Xyloband</h3>
<p>Have you ever seen the xylobands which we wear in concerts and they
flash light according to the music being played. You can make it on your
own with just basic knowledge of opamps !</p>
<p>Formally the problem statement would be make an LED blink on the beats
of music.</p>
<p>Now the beats of music are essentially the drum sounds which are of the
lowest frequency. So essentially we need to isolate the sound signals
produced made by a drum, amplify them and then make LED toggle on that
frequency.</p>
<p>Here is the circuit of xyloband:</p>
<p><img src="/assets/get-electrified-2/xylo_band_circuit.jpg" alt="xyloband_circuit" /></p>
<p>We start by taking the input of music via a microphone. We can model the
microphone as unipolar resistor. Therefore we have made a voltage
divider circuit in which one resistor is the microphone itself. When the
sound waves hit the microphone, the resistance of the microphone changes
according to the music.</p>
<p>So theoretically we have a voltage output of music but you can’t
directly apply this output to the LED. The reasons being :</p>
<ol>
<li>The voltage output is in order of about 10-20 millivolts.</li>
<li>The output contains all the frequencies.</li>
</ol>
<p>To amplify the signal we are using opamps.The next part of the circuit
you can see is an inverting voltage amplifier made by using an Opamp.
The gain factor of this amplifier is simply the ratio of resistances
connected which is 100/1.5 = 66.67.</p>
<p>Now we need only the signals corresponding to the drum frequencies. But
we have all frequencies corresponding to all the instruments. We need to
“filter” out these frequencies. Since the frequency we want is the
lowest of all we need to design a low pass filter.</p>
<p>Here too opamp comes to help. As you can see in the circuit we have
designed a low pass filter using opamp. The values of resistor and
capacitor is chosen such that the cutoff frequency of the filter is just
above the maximum frequency of drum beats.</p>
<p>Now after filtering the signal this is what we have in our hands : An
amplified output corresponding the the beats of the music. Note that
after filtering the higher frequencies have been attenuated.</p>
<p>Now what I want is that if I get the amplified output of drumbeats the
my LED should turn ON and if get the attenuated voltage of higher
frequencies then my LED should be OFF.</p>
<p>So basically we need to “compare” the signals with respect to a particular value.
So that’s what our next part of the circuit is; a comparator. The
reference voltage of comparator has been set by using a simple voltage
divider.</p>
<p>And we are done with our circuit and you are ready to make the LED dance
on your music beats.</p>
<h3 id="audio-amplifier">Audio Amplifier</h3>
<p>In this circuit we play music through our cell phones via an external
speaker.</p>
<p>Here is the circuit diagram of the Audio Amplifier:</p>
<p><img src="/assets/get-electrified-2/audio_amplifier_circuit.jpg" alt="audio_amplifier_circuit" /></p>
<p>Can you see an AC source in the left part of circuit ? That’s where we
connect the audio jack output from our cell phones.</p>
<p>Now to drive a speaker we need sufficient voltage and current. The
current and voltage that we receive from the audio jack is not
sufficient to drive the speaker. Therefore in the above circuit we are
amplifying the signal in two stages; one is voltage amplifier and the
another one is current amplifier.</p>
<p>The voltage amplification is done by opamp. The current is amplified
using a differential amplifier made by an npn and a pnp transistor. The
final output is then connected to the speaker and you have the speaker
playing the music.</p>
<p>Let’s have a look at how the things turned out to be :)</p>
<iframe width="1280" height="720" src="https://www.youtube.com/embed/So6K92vzHUw" frameborder="0" allowfullscreen=""></iframe>
</content>
</entry>
<entry>
<title>The Tech Behind Games</title>
<link href="https://elec-club-iitb.github.io/blog/2016/08/the-tech-behind-games/"/>
<updated>2016-08-31T00:00:00+00:00</updated>
<id>https://elec-club-iitb.github.io/blog/2016/08/the-tech-behind-games</id>
<content type="html"><p>Gaming is one of the most popular form of entertainment (and probably will hold this position forever).
Also, mobile gaming is on a boom now a days. Almost every good game needs its controls to be intuitive and flexible.
There has been a lot of research and upgradations in the field of motion sensing.
Some of the major breakthroughs are Gyroscope, Accelerometer, Magnetometer, etc. Let’s know about these in detail.</p>
<h3 id="motion-sensing">Motion Sensing</h3>
<p>One key element of interaction is local motion of the phone, such as linear acceleration, rotational velocity, etc.</p>
<p><img src="/assets/the-tech-behind-games/accel_gyro.jpg" alt="accel_gyro" /></p>
<ul>
<li>
<p><strong>Accelerometer</strong></p>
<p>Have you ever wondered how your phone manages to know what direction you are holding it?
It uses a device called accelerometer. An accelerometer is a device that measures linear acceleration.
As it has to measure acceleration, force should come in picture somewhere.
It measures force using a loaded capacitor with one plate attached to a spring.
A simplistic model is where one plate is fixed, and the other has the mass of the load attached to a spring.
This spring will change its amount of compression (and hence distance between plates) based on the force
applied to the capacitor. This change in distance leads to a change in capacitance
, which is measured and used to determine the acceleration of the device. Interesting isn’t it!
One capacitor is used for each axis X, Y, Z and hence we can get the acceleration
vector in 3D.</p>
</li>
</ul>
<p><img src="/assets/the-tech-behind-games/capacitor_diagram.jpg" alt="capacitor" /></p>
<ul>
<li>
<p><strong>Gyroscope</strong></p>
<p>It is a device used to measure the angular velocity.
It basically consists a wheel or disc mounted so that it can spin rapidly
about an axis which itself is free to alter in any direction.
Also it is connected to different capacitors at its edges such that when the
device rotates and the disc moves there is a subtle change in the capacitance
(similar model like the accelerometer) which helps us to determine the
magnitude of the angular acceleration of the device.
Also, more than one capacitors are used so that we get an idea of the
direction in which the device is rotated.
One important observation here is that setup based on torsion strain cannot
be used as we have to measure angular velocity and not the angular acceleration.</p>
</li>
<li>
<p><strong>Magnetometer</strong></p>
<p>In the very basic sense a magnetormeter is a compass.
It provides mobile phones with a orientation in relation to the Earth’s magnetic field.
There are two types of magnetometers, which use Hall-effect and others which
use Magneto-resistive effects, the former are used on a large scale.
In these kinds of magnetometers, a conductive plate is connected to a
complete circuit so that electrons flow through it is continuous.
When the device comes in the influence of a magnetic field, there is a deflection
in the path of the electrons due to which a potential difference is created
across the edges of the plate perpendicular to the flow of current.
By measuring this potential difference the magnetic field vector around is determined.</p>
</li>
</ul>
<h3 id="gps-global-positioning-system">GPS (Global Positioning System)</h3>
<p>The United States began the GPS project in 1973 to overcome the limitations of
previous navigation systems. Later they thought that everyone should use this technology.
The purpose was providing geographical position in all weather conditions anywhere on or near Earth.</p>
<h4 id="working">Working</h4>
<p>This comprises of a network of 27 satellites (of which 3 are for backup)
which have a transmitter attached (they do not have a receiver).
They basically transmit data in the form of electromagnetic waves.
The transmitted data consists of three chunks:</p>
<ul>
<li>A pre-determined random string</li>
<li>The satellite’s current orbital position and time of transmission</li>
<li>health data for monitoring</li>
</ul>
<p>The receiver also records when it recieved this transmission.
Thus we know the time of transmitting and using this info we can calculate the
distance between us and the satellite as we also know the time we received the wave,
and hence time it took to travel the distance. The speed of the wave is equal
to the speed of light because it is an electromagnetic wave.</p>
<p><img src="/assets/the-tech-behind-games/gps.jpg" alt="gps" /></p>
<p>Using this distance measurement from 3 different satellites and their orbital position
we get three spheres as loci of our position. The earth is the fourth sphere. Using coordinate geometry
we can find the intersection of these spheres to give one single point in 3D space
which will be our location.</p>
<p>So 3 satellites are enough to pinpoint our location, but to increase the accuracy 4-5 satellites are generally used.</p>
<h3 id="augmented-reality">Augmented Reality</h3>
<p>As the name suggests it basically enhances the real world by adding the digital
graphics to real world. This is done by displaying the real world and additional
“augmented” data together on one screen.</p>
<p><img src="/assets/the-tech-behind-games/ar.jpg" alt="AR" /></p>
<p>This has varied applications like visual art, greeting cards, video games
(any fans of Pokemon Go or Ingress here!)</p>
<p>In this, we basically take an image, detect a pattern and attach an object to it.
Let me explain by giving an example, while playing pokemon go suppose a wild magikarp appears,
the camera will take input of the image in front of it and detect any water body
(the shades of colour which represent water are detected) present.
It will then deploy the water type pokemon over that water body.
There other components like angle, height, width, etc. are also considered to give 3D effects.</p>
<p>Any game like Pokemon Go or Ingress will interface these sensors and use this
data to enhance your experience of interactivity with the game. They use AR
to give an immersive feel to the game, much like you are in the game’s world
and playing it in real life!</p>
</content>
</entry>
<entry>
<title>Functioning of L293D motor driver</title>
<link href="https://elec-club-iitb.github.io/blog/2016/08/l293d/"/>
<updated>2016-08-14T00:00:00+00:00</updated>
<id>https://elec-club-iitb.github.io/blog/2016/08/l293d</id>
<content type="html"><p>Last year I entered IIT Bombay and had my first face off with the modern
tech then. We had a bot racing competition called XLR8 in which we have
to prepare a bot on our own and race it with others so as to win. Seems
easy? Not as much as it seems to be .</p>
<p>It’s not just about making and winning, it’s about learning too . All
the components we are getting and assembling we should have knowledge
about them. How, when ,where they work and are used should be thing we
should really be taking care of .
So while we were making the bot we came across this most intriguing
small chip, <strong>L293D</strong>. This is basically a motor driver, something which
helps in controlling motors (in our case, the wheels of the bot). A
first look at the connections and we feel it’s all too mixed up! Wires
entangled into one another and what goes where, NO IDEA!</p>
<p>But actually it’s working is pretty easy. Here, I will try to explain it
in a simple way.</p>
<p>So let’s explore this motor driver and see what we can do to learn it
(at least with a data sheet :P )</p>
<p>Presuming we have this driver , its datasheet and zeal to learn.</p>
<p><img src="/assets/l293d/image00.png" alt="image" /></p>
<p>It looks like this from outside and the connections inside are :</p>
<p><img src="/assets/l293d/image01.png" alt="image" /></p>
<p><strong>Working Of L293D</strong></p>
<p>L293D is a motor driver 16 pin IC which can be used to run a set of two
DC motors at a time. To power itself it requires 5V voltage through VCC1
and can deliver up to 12 volts through VCC2.</p>
<p>To understand the working of L293D, we first need to know about a
component called H-Bridge</p>
<p><strong>H-Bridge</strong><br />
A H-bridge looks like following :</p>
<p><img src="/assets/l293d/image02.png" alt="image" /></p>
<p>It is used to apply voltage across a load( here, a motor ) in both the
directions. So we can easily infer from this if the voltage across the
motor is reversed , its direction of rotation is also reversed and hence
this is used to drive the motor in both the directions.</p>
<ul>
<li>If switches S1 and S4 are closed then motor rotates clockwise.</li>
<li>If switches S2 and S3 are closed then motor rotates anticlockwise.</li>
<li>If S1 and S3 or S2 and S4 are closed then motor stops rotating.</li>
<li>If all are left open motor moves freely.</li>
<li>Never close S1 and S2 or S3 and S4 or all of them simultaneously.</li>
</ul>
<p>L293D is, infact, a dual H bridge IC used to drive motors in both
forward and backward direction through various combinations of inputs
that we will look later. The first H-Bridge is formed by Left Hand Side
pins of L293D (see diagram) while the second is formed by the right hand
side ones.</p>
<p>To ensure that motor attach to it at both sides run, PIN 1 and PIN 9 (
ENABLE PINS ) should be high. Enable pins can be a considered as a
switch to this IC , if it’s high then switch is on and motor will work (
according to the provided proper input ) and if it is low, meaning
switch is off, the motors won’t respond to the corresponding inputs.</p>
<p>The voltage we supply at VCC1 is used to power the L293D for its working
and at VCC2 we get the output used for driving its motors. Now the
output at VCC2 depends on the voltage you supplied at VCC1. The fraction
of voltage you supply at VCC1 appears in the same fraction at VCC2.</p>
<p><strong>CONNECTIONS IN L293D</strong></p>
<ol>
<li>
<p>Pin1 and Pin9 are “Enable” pins or the switch pins as you can say.
They should be connected to +5V for the drivers to function (for
the motor to follow the inputs). If they pulled low (GND), then
the outputs will be turned off regardless of the input states,
stopping the motors.</p>
</li>
<li>
<p>Pin4, Pin5, Pin12 and Pin 13 are ground pins which should ideally be
connected to microcontroller’s ground.</p>
</li>
<li>
<p>Pin2, Pin7, Pin10 and Pin15 are logic input pins. These are control
pins which should be connected to microcontroller pins or whatever
is the input to L293D. Pin2 and Pin7 control the left motor ;
Pin10 and Pin15 control the right motor. (as shown in diagram)</p>
</li>
<li>
<p>Pin3, Pin6, Pin11, and Pin 14 are output pins. Tie Pin3 and Pin6 to
the left motor, Pin11 and Pin 14 to right motor. Note that there
is a bijection between the input pins and output pins.</p>
</li>
<li>
<p>Pin16 powers the IC and it should be connected to regulated +5Volts.</p>
</li>
<li>
<p>Pin8 powers the two motors and should be connected to positive lead
of a secondary battery. As per the datasheet, supply voltage can
be as high as 36 Volts.</p>
<p>As we can see the highest output is 36V so considerably larger
motor can also be driven using this IC. ( Oh I see this IC is
useful :P )</p>
<p>Keep in mind all these connections while making your bot as well
the reason behind these connections. This makes debugging easy.
I have experienced this, we randomly did all the connections and
wondering why our bot isn’t working until some told enable pin is
set too low!</p>
</li>
</ol>
<p><strong>LOGIC TABLE FOR L293D</strong></p>
<p><img src="/assets/l293d/image03.png" alt="image" /></p>
<p>Similarly for PIN 9 ( ~PIN 1 ) , PIN 10( ~PIN2 ) and PIN 15 ( ~PIN7 ).</p>
<p><strong>EXPLANATION OF THE TABLE</strong></p>
<p>Now no need to memorize the high and low , work on the logic !<br />
PIN 1 and PIN 9 are your enable pins so they need to be kept high and
otherwise it doesn’t matter what your input is , your motors will not
move.<br />
Now we should have a potential difference between the output terminals,
so that it appears across motor and it rotates. For that to happen there
should be a potential difference at the input terminals too (since there
is a bijection between the input and output pins) ! Hence, the truth
table is justified.</p>
<p><strong>DO’s AND DONT’s</strong></p>
<p>You have learnt about L293D but before moving on to any kind of
tinkering you should know what to experiment and what not to ( unless
you are so enthusiastic to see whats like a blown up L293D). Here we go:</p>
<ol>
<li>
<p>Make sure you connect all the pins properly such that no two pins are
shorted except the ground pins.</p>
</li>
<li>
<p>Make sure the IC is connected in proper orientation. The pin to the
left of the small semicircle of the IC at the top is the first pin.</p>
</li>
<li>
<p>Make sure the supply voltage is not greater than 5 volts for IC and
more than 36 volts for motor.</p>
</li>
<li>
<p>Remove the input pins when not required to avoid any unnecessary
heating of IC.</p>
</li>
</ol>
<p>Happy tinkering ! :D</p>
</content>
</entry>
<entry>
<title>Making a Sound Meter in Python</title>
<link href="https://elec-club-iitb.github.io/blog/2016/08/sound-meter/"/>
<updated>2016-08-04T00:00:00+00:00</updated>
<id>https://elec-club-iitb.github.io/blog/2016/08/sound-meter</id>
<content type="html"><p>Those who have seen the 3 blocks of audience in PCSA compete during the STAB Orientation for the loudest cheer, know what this Sound Meter is.</p>
<h2 id="target">Target</h2>
<p>To analyse any incoming sound(be it mic or laptop microphone) and find its maximum volume. Actually, using other detailed operations you can estimate the frequency etc. Basically, once we read the audio input stream we can use the desired computations on it.</p>
<h2 id="plan-of-action">Plan of action</h2>
<p>This is roughly what we need to do:</p>
<ol>
<li>Read the input from the laptop microphone or the mic(in our case, that requires setting it to default recording device)</li>
<li>Find the maximum value of the sound channels over a chunk of inputs.</li>
<li>Display it!</li>
</ol>
<h2 id="libraries-used">Libraries used:</h2>
<p><strong>pyaudio</strong> for audio stream input.
<strong>audioop</strong> for max value analysis.
<strong>pygame</strong> for display.</p>
<figure class="highlight"><pre><code class="language-python" data-lang="python"><span class="kn">import</span> <span class="nn">time</span><span class="o">,</span> <span class="nn">audioop</span>
<span class="kn">import</span> <span class="nn">pygame</span>
<span class="kn">import</span> <span class="nn">pyaudio</span>
<span class="kn">import</span> <span class="nn">wave</span>
<span class="c">#Initialisation for PyAudio</span>
<span class="n">CHUNK</span> <span class="o">=</span> <span class="mi">1024</span>
<span class="n">FORMAT</span> <span class="o">=</span> <span class="n">pyaudio</span><span class="o">.</span><span class="n">paInt16</span>
<span class="n">CHANNELS</span> <span class="o">=</span> <span class="mi">2</span>
<span class="n">RATE</span> <span class="o">=</span> <span class="mi">44100</span>
<span class="n">RECORD_SECONDS</span> <span class="o">=</span> <span class="mi">5</span>
<span class="c">#Object</span>
<span class="n">p</span> <span class="o">=</span> <span class="n">pyaudio</span><span class="o">.</span><span class="n">PyAudio</span><span class="p">()</span>
<span class="n">stream</span> <span class="o">=</span> <span class="n">p</span><span class="o">.</span><span class="nb">open</span><span class="p">(</span><span class="n">format</span><span class="o">=</span><span class="n">FORMAT</span><span class="p">,</span> <span class="n">channels</span><span class="o">=</span><span class="n">CHANNELS</span><span class="p">,</span> <span class="n">rate</span><span class="o">=</span><span class="n">RATE</span><span class="p">,</span> <span class="nb">input</span><span class="o">=</span><span class="bp">True</span><span class="p">,</span> <span class="n">frames_per_buffer</span><span class="o">=</span><span class="n">CHUNK</span><span class="p">)</span>
<span class="c">#PyGame initialisations and basic objects</span>
<span class="n">pygame</span><span class="o">.</span><span class="n">init</span><span class="p">()</span>
<span class="n">screensize</span> <span class="o">=</span> <span class="p">(</span><span class="mi">900</span><span class="p">,</span> <span class="mi">600</span><span class="p">)</span>
<span class="n">screen</span><span class="o">=</span><span class="n">pygame</span><span class="o">.</span><span class="n">display</span><span class="o">.</span><span class="n">set_mode</span><span class="p">(</span><span class="n">screensize</span><span class="p">)</span>
<span class="n">pygame</span><span class="o">.</span><span class="n">display</span><span class="o">.</span><span class="n">set_caption</span><span class="p">(</span><span class="s">"Shout harder.. :D"</span><span class="p">)</span>
<span class="c">#Defining colors</span>
<span class="n">WHITE</span><span class="o">=</span><span class="p">(</span><span class="mi">255</span><span class="p">,</span><span class="mi">255</span><span class="p">,</span><span class="mi">255</span><span class="p">)</span>
<span class="n">RED</span><span class="o">=</span><span class="p">(</span><span class="mi">255</span><span class="p">,</span><span class="mi">128</span><span class="p">,</span><span class="mi">128</span><span class="p">)</span>
<span class="n">YELLOW</span><span class="o">=</span><span class="p">(</span><span class="mi">255</span><span class="p">,</span><span class="mi">255</span><span class="p">,</span><span class="mi">128</span><span class="p">)</span>
<span class="n">BLUE</span><span class="o">=</span><span class="p">(</span><span class="mi">0</span><span class="p">,</span><span class="mi">0</span><span class="p">,</span><span class="mi">255</span><span class="p">)</span>
<span class="c">#Loop till close button clicked</span>
<span class="n">done</span><span class="o">=</span><span class="bp">False</span>
<span class="n">clock</span><span class="o">=</span><span class="n">pygame</span><span class="o">.</span><span class="n">time</span><span class="o">.</span><span class="n">Clock</span><span class="p">()</span>
<span class="c">#variables</span>
<span class="n">score</span><span class="o">=</span><span class="p">[]</span>
<span class="n">width</span><span class="o">=</span><span class="mf">0.8</span>
<span class="n">margin</span> <span class="o">=</span> <span class="mi">20</span>
<span class="n">samples_per_section</span> <span class="o">=</span> <span class="n">screensize</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span><span class="o">/</span><span class="mi">3</span> <span class="o">-</span> <span class="mi">2</span><span class="o">*</span><span class="n">margin</span>
<span class="n">sound_tracks</span> <span class="o">=</span> <span class="p">[[</span><span class="mi">0</span><span class="p">]</span><span class="o">*</span><span class="n">samples_per_section</span><span class="p">]</span><span class="o">*</span><span class="mi">3</span>
<span class="n">max_value</span> <span class="o">=</span> <span class="p">[</span><span class="mi">0</span><span class="p">]</span><span class="o">*</span><span class="mi">3</span>
<span class="n">current_section</span> <span class="o">=</span> <span class="mi">0</span>
<span class="k">while</span> <span class="ow">not</span> <span class="n">done</span><span class="p">:</span>
<span class="c">#Limits CPU usage to max 10 times per second</span>
<span class="c">#Not required here because already the for loop takes averages over some time</span>
<span class="c">#clock.tick(10)</span>
<span class="n">total</span><span class="o">=</span><span class="mi">0</span>
<span class="c">#Now we read data from device for around one second</span>
<span class="k">for</span> <span class="n">i</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="mi">0</span><span class="p">,</span><span class="mi">2</span><span class="p">):</span>
<span class="c">#l,data = inp.read()</span>
<span class="n">data</span><span class="o">=</span><span class="n">stream</span><span class="o">.</span><span class="n">read</span><span class="p">(</span><span class="n">CHUNK</span><span class="p">)</span>
<span class="c">#oreo_sound.append(data)</span>
<span class="k">if</span> <span class="bp">True</span><span class="p">:</span>
<span class="n">reading</span><span class="o">=</span><span class="n">audioop</span><span class="o">.</span><span class="nb">max</span><span class="p">(</span><span class="n">data</span><span class="p">,</span> <span class="mi">2</span><span class="p">)</span>
<span class="n">total</span><span class="o">=</span><span class="n">total</span><span class="o">+</span><span class="n">reading</span>
<span class="n">time</span><span class="o">.</span><span class="n">sleep</span><span class="p">(</span><span class="o">.</span><span class="mo">0001</span><span class="p">)</span>
<span class="c">#any scaling factor</span>
<span class="n">total</span><span class="o">=</span><span class="n">total</span><span class="o">/</span><span class="mi">100</span>
<span class="n">sound_tracks</span><span class="p">[</span><span class="n">current_section</span><span class="p">]</span> <span class="o">=</span> <span class="n">sound_tracks</span><span class="p">[</span><span class="n">current_section</span><span class="p">][</span><span class="mi">1</span><span class="p">:]</span> <span class="o">+</span> <span class="p">[</span><span class="n">total</span><span class="p">]</span>
<span class="n">max_value</span><span class="p">[</span><span class="n">current_section</span><span class="p">]</span> <span class="o">=</span> <span class="nb">max</span><span class="p">(</span><span class="n">max_value</span><span class="p">[</span><span class="n">current_section</span><span class="p">],</span> <span class="n">total</span><span class="p">)</span>
<span class="n">screen</span><span class="o">.</span><span class="n">fill</span><span class="p">(</span><span class="n">WHITE</span><span class="p">)</span>
<span class="c"># draw highlighted section</span>
<span class="n">pygame</span><span class="o">.</span><span class="n">draw</span><span class="o">.</span><span class="n">rect</span><span class="p">(</span><span class="n">screen</span><span class="p">,</span><span class="n">YELLOW</span><span class="p">,(</span><span class="n">screensize</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span><span class="o">/</span><span class="mi">3</span><span class="o">*</span><span class="n">current_section</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span><span class="n">screensize</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span><span class="o">/</span><span class="mi">3</span><span class="p">,</span> <span class="n">screensize</span><span class="p">[</span><span class="mi">1</span><span class="p">]))</span>
<span class="k">for</span> <span class="n">i</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="mi">3</span><span class="p">):</span>
<span class="n">sectionx</span> <span class="o">=</span> <span class="n">i</span><span class="o">*</span><span class="n">screensize</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span><span class="o">/</span><span class="mi">3</span> <span class="o">+</span> <span class="n">margin</span>
<span class="c">#add meet wala last year ka feature</span>
<span class="n">pygame</span><span class="o">.</span><span class="n">draw</span><span class="o">.</span><span class="n">rect</span><span class="p">(</span><span class="n">screen</span><span class="p">,</span><span class="n">RED</span><span class="p">,(</span><span class="n">sectionx</span><span class="p">,</span> <span class="n">screensize</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span> <span class="o">-</span> <span class="n">max_value</span><span class="p">[</span><span class="n">i</span><span class="p">],</span><span class="n">screensize</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span><span class="o">/</span><span class="mi">3</span> <span class="o">-</span> <span class="mi">2</span><span class="o">*</span><span class="n">margin</span><span class="p">,</span> <span class="n">max_value</span><span class="p">[</span><span class="n">i</span><span class="p">]))</span>
<span class="k">for</span> <span class="n">j</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="mi">0</span><span class="p">,</span><span class="n">screensize</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span><span class="o">/</span><span class="mi">3</span> <span class="o">-</span> <span class="mi">2</span><span class="o">*</span><span class="n">margin</span><span class="p">):</span>
<span class="n">x</span> <span class="o">=</span> <span class="n">j</span> <span class="o">+</span> <span class="n">sectionx</span>
<span class="n">y</span> <span class="o">=</span> <span class="n">screensize</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span> <span class="o">-</span> <span class="n">sound_tracks</span><span class="p">[</span><span class="n">i</span><span class="p">][</span><span class="n">j</span><span class="p">]</span>
<span class="n">pygame</span><span class="o">.</span><span class="n">draw</span><span class="o">.</span><span class="n">rect</span><span class="p">(</span><span class="n">screen</span><span class="p">,</span><span class="n">BLUE</span><span class="p">,(</span><span class="n">x</span><span class="p">,</span> <span class="n">y</span><span class="p">,</span> <span class="mi">1</span><span class="p">,</span> <span class="n">sound_tracks</span><span class="p">[</span><span class="n">i</span><span class="p">][</span><span class="n">j</span><span class="p">]))</span>
<span class="c">#frame flip must happen after all drawing commands</span>
<span class="n">pygame</span><span class="o">.</span><span class="n">display</span><span class="o">.</span><span class="n">flip</span><span class="p">()</span>
<span class="c">#Set close button event</span>
<span class="k">for</span> <span class="n">event</span> <span class="ow">in</span> <span class="n">pygame</span><span class="o">.</span><span class="n">event</span><span class="o">.</span><span class="n">get</span><span class="p">():</span>
<span class="k">if</span> <span class="n">event</span><span class="o">.</span><span class="nb">type</span><span class="o">==</span><span class="n">pygame</span><span class="o">.</span><span class="n">QUIT</span><span class="p">:</span>
<span class="n">done</span><span class="o">=</span><span class="bp">True</span>
<span class="k">if</span> <span class="n">event</span><span class="o">.</span><span class="nb">type</span><span class="o">==</span><span class="n">pygame</span><span class="o">.</span><span class="n">MOUSEBUTTONUP</span> <span class="p">:</span>
<span class="k">if</span> <span class="n">event</span><span class="o">.</span><span class="n">button</span> <span class="o">==</span> <span class="mi">3</span><span class="p">:</span>
<span class="c"># right button pressed, clear all arrays</span>
<span class="n">sound_tracks</span> <span class="o">=</span> <span class="p">[[</span><span class="mi">0</span><span class="p">]</span><span class="o">*</span><span class="n">samples_per_section</span><span class="p">]</span><span class="o">*</span><span class="mi">3</span>
<span class="n">max_value</span> <span class="o">=</span> <span class="p">[</span><span class="mi">0</span><span class="p">]</span><span class="o">*</span><span class="mi">3</span>
<span class="n">current_section</span> <span class="o">=</span> <span class="mi">0</span>
<span class="k">else</span><span class="p">:</span>
<span class="n">pos</span> <span class="o">=</span> <span class="n">pygame</span><span class="o">.</span><span class="n">mouse</span><span class="o">.</span><span class="n">get_pos</span><span class="p">()</span>
<span class="n">current_section</span> <span class="o">=</span> <span class="p">(</span><span class="n">pos</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">*</span> <span class="mi">3</span><span class="p">)</span> <span class="o">/</span> <span class="n">screensize</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span>
<span class="k">print</span> <span class="n">pos</span><span class="p">,</span> <span class="n">current_section</span>
<span class="c">#clearing the resources</span>
<span class="n">pygame</span><span class="o">.</span><span class="n">quit</span><span class="p">()</span>
<span class="n">stream</span><span class="o">.</span><span class="n">stop_stream</span><span class="p">()</span>
<span class="n">stream</span><span class="o">.</span><span class="n">close</span><span class="p">()</span>
<span class="n">p</span><span class="o">.</span><span class="n">terminate</span><span class="p">()</span>
<span class="n">pygame</span><span class="o">.</span><span class="n">quit</span><span class="p">()</span></code></pre></figure>
<p>Have fun!</p>
</content>
</entry>
<entry>
<title>Sudoku Solver</title>
<link href="https://elec-club-iitb.github.io/blog/2016/07/sudoku-solver/"/>
<updated>2016-07-31T00:00:00+00:00</updated>
<id>https://elec-club-iitb.github.io/blog/2016/07/sudoku-solver</id>
<content type="html"><p><strong>Sudoku Solver</strong> is the collection of very basic image processing techniques. A very good way to start is the OpenCV library which can be compiled on almost all the platforms. <strong>OpenCV</strong>(open source computer vision )is a library of programming functions mainly aimed at real time computer vision. Through this project ,my main motivation was to explore what OpenCV offers in a little bit detail . There are already many blogs dealing with how to recognise a whole sudoku puzzle but it was nevertheless a pleasant experience doing it on my own and writing this blog ( It is pretty obvious that I too would have been lost without all those online resources , blogs , and documentations.)</p>
<h3 id="what-actually-this-project-does">What actually this project does?</h3>
<p>It takes an input image of a sudoku and processes the image and identifies the all the whole suduko and return the answer of the sudoku.
It involves two major challenges:</p>
<ol>
<li>Image recognition</li>
<li>Solving the sudoku puzzle</li>
</ol>
<p>I was more interested in the image processing part as there are fixed algorithm for solving the sudoku puzzle so my main focus in this blog would be the image processing part.</p>
<h3 id="the-major-steps-this-will-involve-are"><strong>The major steps this will involve are:</strong></h3>
<ol>
<li> Reading an image</li>
<li> Preprocessing the image ( removal of noises and thresholding the image)</li>
<li> Finding the sudoku square out of the whole image</li>
<li> Extracting the sub-grids of the sudoku.</li>
<li>Recognising the digits (OCR)</li>
</ol>
<h3 id="we-also-need-to-make-a-few-assumptions-"><strong>We also need to make a few assumptions :</strong></h3>
<ol>
<li>In the image , the largest square would be that of the sudoku image</li>
<li>The puzzle would be oriented reasonably oriented.</li>
</ol>
<p><strong>So let’s get started, </strong></p>
<p>First of all we need is an input image. We need to load a sudoku image .</p>
<p><img src="/assets/sudoku-solver/image1.jpg" alt="image" /></p>
<figure class="highlight"><pre><code class="language-c" data-lang="c"> <span class="n">Mat</span> <span class="n">src</span> <span class="o">=</span> <span class="n">imread</span><span class="p">(</span><span class="s">"sudoku.jpg"</span><span class="p">,</span><span class="n">CV_LOAD_IMAGE_UNCHANGED</span><span class="p">);</span></code></pre></figure>
<p>After loading the image ,the first thing to do in any image processing problem is to reduce the amount of data you are dealing with.We started with a full colour high resolution image.The first thing we can do is to convert the image into a gray scale as looking at our sample image having colour is of no use to us.</p>
<figure class="highlight"><pre><code class="language-c" data-lang="c"> <span class="n">Mat</span> <span class="n">srcb</span><span class="p">;</span>
<span class="n">cvtColor</span><span class="p">(</span><span class="n">src</span><span class="p">,</span> <span class="n">srcb</span><span class="p">,</span> <span class="n">COLOR_BGR2GRAY</span><span class="p">);</span></code></pre></figure>
<h3 id="image-processing">Image Processing:</h3>
<p>After we have converted the image into a gray scale image we need to remove the noises from the image and smoothen the image as without smoothing the image we deal with extra objects which are not needed so it is necessary to remove the noises. There are many functions available in the OpenCV library for blurring the image like blur , GaussianBlur , MedianBlur . I tried them all and the best result I got out of them was with gaussian blur so I used it . Next , what we need to do is to remove other extra information . We are going to threshold the image that is we have either the foreground pixel or the background pixel. There are variety of thresholding techniques available to us in OpenCV library. My personal favourite is a simple adaptive threshold .For each pixel in the image it takes the average value of the surrounding area.</p>
<figure class="highlight"><pre><code class="language-c" data-lang="c"> <span class="n">Mat</span> <span class="n">smooth</span><span class="p">;</span>
<span class="n">Mat</span> <span class="n">thresholded</span><span class="p">;</span>
<span class="n">GaussianBlur</span><span class="p">(</span><span class="n">srcb</span><span class="p">,</span> <span class="n">smooth</span><span class="p">,</span> <span class="n">Size</span><span class="p">(</span><span class="mi">11</span><span class="p">,</span> <span class="mi">11</span><span class="p">),</span> <span class="mi">0</span><span class="p">,</span> <span class="mi">0</span><span class="p">);</span> <span class="c1">//removing noises
</span>
<span class="n">adaptiveThreshold</span><span class="p">(</span><span class="n">smooth</span><span class="p">,</span> <span class="n">thresholded</span><span class="p">,</span> <span class="mi">255</span><span class="p">,</span> <span class="n">ADAPTIVE_THRESH_MEAN_C</span><span class="p">,</span><span class="n">THRESH_BINARY_INV</span><span class="p">,</span> <span class="mi">15</span><span class="p">,</span> <span class="mi">5</span><span class="p">);</span></code></pre></figure>
<p> I have done just noise removal and adaptive thresholding and it is working so haven’t done anything extra. Below is the result:</p>
<p><img src="/assets/sudoku-solver/image2.png" alt="image" /></p>
<h3 id="extracting-the-sudoku-">Extracting the Sudoku :</h3>
<p>Now after thresholding we need to find out the sudoku square , for this we made an assumption the main thing in our image would be the sudoku so we need to find the square with the largest area and it would be our sudoku.</p>
<p>So one thing is very important the sudoku square should be largest otherwise our method fails.</p>
<p>We start by finding the countours in our thresholded image.</p>
<figure class="highlight"><pre><code class="language-c" data-lang="c"> <span class="n">vector</span><span class="o">&lt;</span> <span class="n">vector</span> <span class="o">&lt;</span> <span class="n">Point</span> <span class="o">&gt;&gt;</span><span class="n">contours</span><span class="p">;</span>
<span class="n">vector</span> <span class="n">heirarchy</span><span class="p">;</span>
<span class="n">findContours</span><span class="p">(</span><span class="n">thresholded2</span><span class="p">,</span> <span class="n">contours</span><span class="p">,</span> <span class="n">heirarchy</span><span class="p">,</span> <span class="n">CV_RETR_TREE</span><span class="p">,</span><span class="n">CV_CHAIN_APPROX_SIMPLE</span><span class="p">);</span></code></pre></figure>
<p>Now we find the blob with maximum area .First we filter them by area . We consider the blob for the next processing only if its area is greater than a particular value (here , it is 50) . Next , we find out the area of each blob and hence extract the blob which has the maximum area. </p>
<figure class="highlight"><pre><code class="language-c" data-lang="c"> <span class="kt">double</span> <span class="n">area</span><span class="p">;</span> <span class="kt">double</span> <span class="n">maxarea</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span><span class="kt">int</span> <span class="n">p</span><span class="p">;</span>
<span class="k">for</span> <span class="p">(</span><span class="kt">int</span> <span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="n">contours</span><span class="p">.</span><span class="n">size</span><span class="p">();</span> <span class="n">i</span><span class="o">++</span><span class="p">)</span>
<span class="p">{</span>
<span class="n">area</span> <span class="o">=</span> <span class="n">contourArea</span><span class="p">(</span><span class="n">contours</span><span class="p">[</span><span class="n">i</span><span class="p">],</span> <span class="nb">false</span><span class="p">);</span>
<span class="k">if</span> <span class="p">(</span><span class="n">area</span> <span class="o">&gt;</span> <span class="mi">50</span> <span class="p">)</span>
<span class="p">{</span>
<span class="k">if</span> <span class="p">(</span><span class="n">area</span> <span class="o">&gt;</span> <span class="n">maxarea</span><span class="p">)</span>
<span class="p">{</span>
<span class="n">maxarea</span> <span class="o">=</span> <span class="n">area</span><span class="p">;</span>
<span class="n">p</span> <span class="o">=</span> <span class="n">i</span><span class="p">;</span>
<span class="p">}</span>
<span class="p">}</span>
<span class="p">}</span></code></pre></figure>
<p>Now after finding the blob with maximum area we approximate the countour into a polygon. It removes the unwanted coordiante values in the countour and keeps only the corners.</p>
<figure class="highlight"><pre><code class="language-c" data-lang="c"> <span class="kt">double</span> <span class="n">perimeter</span> <span class="o">=</span> <span class="n">arcLength</span><span class="p">(</span><span class="n">contours</span><span class="p">[</span><span class="n">p</span><span class="p">],</span> <span class="nb">true</span><span class="p">);</span>
<span class="n">approxPolyDP</span><span class="p">(</span><span class="n">contours</span><span class="p">[</span><span class="n">p</span><span class="p">],</span> <span class="n">contours</span><span class="p">[</span><span class="n">p</span><span class="p">],</span> <span class="mi">0</span><span class="p">.</span><span class="mo">01</span><span class="o">*</span><span class="n">perimeter</span><span class="p">,</span> <span class="nb">true</span><span class="p">);</span></code></pre></figure>
<p>Now we draw the contour on our image just to check it.</p>
<figure class="highlight"><pre><code class="language-c" data-lang="c"> <span class="n">drawContours</span><span class="p">(</span><span class="n">src</span><span class="p">,</span> <span class="n">contours</span><span class="p">,</span> <span class="n">p</span><span class="p">,</span> <span class="n">Scalar</span><span class="p">(</span><span class="mi">255</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="mi">0</span><span class="p">),</span> <span class="mi">1</span><span class="p">,</span> <span class="mi">8</span><span class="p">);</span></code></pre></figure>
<p><img src="/assets/sudoku-solver/image3.png" alt="image" /></p>
<p>Now we have found out the boundary of the sudoku and next we need to to do is extract this much part and then work on it.</p>
<p>As we have approximated the contours into a square or rectangle we will get only four coordinate that are the corners and now what we need to do is find out which coordinate is of the top-left corner , top-right corner , bottom-left corner , bottom-right corner. As the order of contours in all the image will not be fixed we need to find it out as we have to map the top-left to [0,0] for new image and bottom-right to [449,449] , as we are creating an image of [450,450] you can do it of whichever size you want , therefore we need to identify the correct order of corners otherwise we will get rotated images. The logic I choose to find the respective corners was : First take the sum of x , y coordinates TOP -LEFT has least sum and BOTTOM-RIGHT has the maximum sum. Now the difference i.e y-x TOP-RIGHT has minimum and BOTTOM-LEFT has maximum sum.</p>
<figure class="highlight"><pre><code class="language-c" data-lang="c"> <span class="kt">double</span> <span class="n">sum</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span>
<span class="kt">double</span> <span class="n">prevsum</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span>
<span class="kt">int</span> <span class="n">a</span><span class="p">;</span>
<span class="kt">int</span> <span class="n">b</span><span class="p">;</span>
<span class="kt">double</span> <span class="n">diff1</span><span class="p">;</span>
<span class="kt">double</span> <span class="n">diff2</span><span class="p">;</span>
<span class="kt">double</span> <span class="n">diffprev2</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span>
<span class="kt">double</span> <span class="n">diffprev</span><span class="o">=</span><span class="mi">0</span><span class="p">;</span>
<span class="kt">double</span> <span class="n">prevsum2</span><span class="o">=</span><span class="n">contours</span><span class="p">[</span><span class="n">p</span><span class="p">][</span><span class="mi">0</span><span class="p">].</span><span class="n">x</span> <span class="o">+</span> <span class="n">contours</span><span class="p">[</span><span class="n">p</span><span class="p">][</span><span class="mi">0</span><span class="p">].</span><span class="n">y</span><span class="p">;</span>
<span class="kt">int</span> <span class="n">c</span><span class="p">;</span> <span class="kt">int</span> <span class="n">d</span><span class="p">;</span>
<span class="k">for</span> <span class="p">(</span><span class="kt">int</span> <span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="mi">4</span><span class="p">;</span> <span class="n">i</span><span class="o">++</span><span class="p">)</span>
<span class="p">{</span>
<span class="n">sum</span> <span class="o">=</span> <span class="n">contours</span><span class="p">[</span><span class="n">p</span><span class="p">][</span><span class="n">i</span><span class="p">].</span><span class="n">x</span> <span class="o">+</span> <span class="n">contours</span><span class="p">[</span><span class="n">p</span><span class="p">][</span><span class="n">i</span><span class="p">].</span><span class="n">y</span><span class="p">;</span>
<span class="n">diff1</span> <span class="o">=</span> <span class="n">contours</span><span class="p">[</span><span class="n">p</span><span class="p">][</span><span class="n">i</span><span class="p">].</span><span class="n">x</span> <span class="o">-</span> <span class="n">contours</span><span class="p">[</span><span class="n">p</span><span class="p">][</span><span class="n">i</span><span class="p">].</span><span class="n">y</span><span class="p">;</span>
<span class="n">diff2</span><span class="o">=</span> <span class="n">contours</span><span class="p">[</span><span class="n">p</span><span class="p">][</span><span class="n">i</span><span class="p">].</span><span class="n">y</span> <span class="o">-</span> <span class="n">contours</span><span class="p">[</span><span class="n">p</span><span class="p">][</span><span class="n">i</span><span class="p">].</span><span class="n">x</span><span class="p">;</span>
<span class="k">if</span> <span class="p">(</span><span class="n">diff1</span> <span class="o">&gt;</span> <span class="n">diffprev</span><span class="p">)</span>
<span class="p">{</span>
<span class="n">diffprev</span> <span class="o">=</span> <span class="n">diff1</span><span class="p">;</span>
<span class="n">c</span> <span class="o">=</span> <span class="n">i</span><span class="p">;</span>
<span class="p">}</span>
<span class="k">if</span> <span class="p">(</span><span class="n">diff2</span> <span class="o">&gt;</span> <span class="n">diffprev2</span><span class="p">)</span>
<span class="p">{</span>
<span class="n">diffprev2</span> <span class="o">=</span> <span class="n">diff2</span><span class="p">;</span>
<span class="n">d</span><span class="o">=</span> <span class="n">i</span><span class="p">;</span>
<span class="p">}</span>
<span class="k">if</span> <span class="p">(</span><span class="n">sum</span> <span class="o">&gt;</span> <span class="n">prevsum</span><span class="p">)</span>
<span class="p">{</span>
<span class="n">prevsum</span> <span class="o">=</span> <span class="n">sum</span><span class="p">;</span> <span class="n">a</span> <span class="o">=</span> <span class="n">i</span><span class="p">;</span>
<span class="p">}</span>
<span class="k">if</span> <span class="p">(</span><span class="n">sum</span> <span class="o">&lt;</span> <span class="n">prevsum2</span><span class="p">)</span>
<span class="p">{</span>
<span class="n">prevsum2</span> <span class="o">=</span> <span class="n">sum</span><span class="p">;</span>
<span class="n">b</span> <span class="o">=</span> <span class="n">i</span><span class="p">;</span>
<span class="p">}</span>
<span class="p">}</span></code></pre></figure>
<p>Now we have 4 points in order and now we need corresponding points where they should be mapped.</p>
<figure class="highlight"><pre><code class="language-c" data-lang="c"> <span class="n">Point2f</span> <span class="n">in</span><span class="p">[</span><span class="mi">4</span><span class="p">];</span>
<span class="n">Point2f</span> <span class="n">out</span><span class="p">[</span><span class="mi">4</span><span class="p">];</span>
<span class="n">in</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">=</span> <span class="n">contours</span><span class="p">[</span><span class="n">p</span><span class="p">][</span><span class="n">a</span><span class="p">];</span>
<span class="n">in</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span> <span class="o">=</span> <span class="n">contours</span><span class="p">[</span><span class="n">p</span><span class="p">][</span><span class="n">b</span><span class="p">];</span>
<span class="n">in</span><span class="p">[</span><span class="mi">2</span><span class="p">]</span> <span class="o">=</span> <span class="n">contours</span><span class="p">[</span><span class="n">p</span><span class="p">][</span><span class="n">c</span><span class="p">];</span>
<span class="n">in</span><span class="p">[</span><span class="mi">3</span><span class="p">]</span> <span class="o">=</span> <span class="n">contours</span><span class="p">[</span><span class="n">p</span><span class="p">][</span><span class="n">d</span><span class="p">];</span>
<span class="n">out</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">=</span> <span class="n">Point2f</span><span class="p">(</span><span class="mi">450</span><span class="p">,</span> <span class="mi">450</span><span class="p">);</span>
<span class="n">out</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span> <span class="o">=</span> <span class="n">Point2f</span><span class="p">(</span><span class="mi">0</span><span class="p">,</span> <span class="mi">0</span><span class="p">);</span>
<span class="n">out</span><span class="p">[</span><span class="mi">2</span><span class="p">]</span> <span class="o">=</span> <span class="n">Point2f</span><span class="p">(</span><span class="mi">450</span><span class="p">,</span> <span class="mi">0</span><span class="p">);</span>
<span class="n">out</span><span class="p">[</span><span class="mi">3</span><span class="p">]</span> <span class="o">=</span> <span class="n">Point2f</span><span class="p">(</span><span class="mi">0</span><span class="p">,</span> <span class="mi">450</span><span class="p">);</span></code></pre></figure>
<p>Now we have the input and output array both what we need to do is apply prespective transformation to get the sudoku part required. Prespective transformation maps a point given by x, y in one quadilateral to a new point X ,Y in another quadilateral.</p>
<figure class="highlight"><pre><code class="language-c" data-lang="c"> <span class="n">Mat</span> <span class="n">wrap</span><span class="p">;</span> <span class="n">Mat</span> <span class="n">mat</span><span class="p">;</span>
<span class="n">mat</span> <span class="o">=</span> <span class="n">Mat</span><span class="o">::</span><span class="n">zeros</span><span class="p">(</span><span class="n">src</span><span class="p">.</span><span class="n">size</span><span class="p">(),</span> <span class="n">src</span><span class="p">.</span><span class="n">type</span><span class="p">());</span>
<span class="n">wrap</span> <span class="o">=</span> <span class="n">getPerspectiveTransform</span><span class="p">(</span><span class="n">in</span><span class="p">,</span> <span class="n">out</span><span class="p">);</span>
<span class="n">warpPerspective</span><span class="p">(</span><span class="n">src</span><span class="p">,</span> <span class="n">mat</span><span class="p">,</span> <span class="n">wrap</span><span class="p">,</span> <span class="n">Size</span><span class="p">(</span><span class="mi">450</span><span class="p">,</span> <span class="mi">450</span><span class="p">));</span></code></pre></figure>
<h3 id="the-result-we-get-is">The result we get is:</h3>
<p><img src="/assets/sudoku-solver/image4.png" alt="image" /></p>
<p>Now apply the pre-processing as we did earlier and get the thresholded image and now we need to extract each grids centre the digit and then finally apply OCR.
So, we can extract each grids as we know our image is a matrix of 450<em>450 and therefore our every sub grids will be a matrix of 50</em>50 so we can extract each grid by extracting the sub grids of 50*50 and store all the images in a vector.</p>
<figure class="highlight"><pre><code class="language-c" data-lang="c"> <span class="kt">int</span> <span class="n">m</span><span class="o">=</span><span class="mi">0</span><span class="p">;</span> <span class="kt">int</span> <span class="n">n</span><span class="p">;</span>
<span class="k">for</span> <span class="p">(;</span> <span class="n">m</span> <span class="o">&lt;</span> <span class="mi">450</span><span class="p">;</span> <span class="n">m</span> <span class="o">=</span> <span class="n">m</span> <span class="o">+</span> <span class="mi">50</span><span class="p">)</span>
<span class="p">{</span>
<span class="k">for</span> <span class="p">(</span><span class="n">n</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">n</span> <span class="o">&lt;</span> <span class="mi">450</span><span class="p">;</span> <span class="n">n</span> <span class="o">=</span> <span class="n">n</span> <span class="o">+</span> <span class="mi">50</span><span class="p">)</span>
<span class="p">{</span>
<span class="n">smallimage</span> <span class="o">=</span> <span class="n">Mat</span><span class="p">(</span><span class="n">thresholded31</span><span class="p">,</span> <span class="n">cv</span><span class="o">::</span><span class="n">Rect</span><span class="p">(</span><span class="n">n</span><span class="p">,</span> <span class="n">m</span><span class="p">,</span> <span class="mi">50</span><span class="p">,</span> <span class="mi">50</span><span class="p">));</span>
<span class="n">smallt</span><span class="p">.</span><span class="n">push_back</span><span class="p">(</span><span class="n">smallimage</span><span class="p">);</span>
<span class="p">}</span>
<span class="p">}</span></code></pre></figure>