Smart Speaker | Proximity Potentiometer Proof of Concept

New project! First, here’s a video:

This is the proof of concept for the volume control of the speaker system. In it’s final form, this sensor will be exposed to the outside and will allow users to control the volume without opening the system, preserving the fidelity of the inside. For example, imagine a user is at the beach and wants to change the volume but they have sand covered hands or wet hands. This system will solve that problem.

The sensor is the Sharp GP2Y0A41SK0F. Here are some very very macro shots of sensors inner workings.

But now for what you came here for, the code. It’s very poorly commented as this is just a prototype, but it’s better than nothing. As this project progresses I’ll posted updated versions of this code.

This demo also relies heavily this shift register. I still haven’t decided if i’m going to use a buzzer to interact with the user or if I’m going to use these bar graphs.

int SER_Pin = 10;   //pin 14 on the 75HC595
int RCLK_Pin = 11;  //pin 12 on the 75HC595
int SRCLK_Pin = 12; //pin 11 on the 75HC595

//How many of the shift registers - change this
#define number_of_74hc595s 4 

//do not touch
#define numOfRegisterPins number_of_74hc595s * 8

boolean registers[numOfRegisterPins];

int detect_led = 2;

int setlevelMode0_led = 3;
int setlevelMode1_led = 4;
int setlevelMode2_led = 5;

int seeking_led = 6;

int check_val = 8;

void setup(){
  pinMode(SER_Pin, OUTPUT);
  pinMode(RCLK_Pin, OUTPUT);
  pinMode(SRCLK_Pin, OUTPUT);
  //reset all register pins
  clearRegisters();
  writeRegisters();

  pinMode(detect_led, OUTPUT);

  pinMode(setlevelMode0_led, OUTPUT);
  pinMode(setlevelMode1_led, OUTPUT);
  pinMode(setlevelMode2_led, OUTPUT);

  pinMode(seeking_led, OUTPUT);

  Serial.begin(9600);
}

int prelevel_0 = 0;
int prelevel_1 = 0;
int prelevel_2 = 0;
int prelevel_3 = 0;
int prelevel_4 = 0;
int prelevel_5 = 0;
int prelevel_6 = 0;
int prelevel_7 = 0;
int prelevel_8 = 0;
int prelevel_9 = 0;

int pre_positions[10] = {prelevel_0, prelevel_1, prelevel_2, prelevel_3, prelevel_4, prelevel_5, prelevel_6, prelevel_7, prelevel_8, prelevel_9};

void loop(){
  for(int i = 0; i <= 9; i = i + 1){
    writebargraph(0,map(analogRead(0),20,600,0,9));
    pre_positions[i] = map(analogRead(0),20,600,0,9);
    if(pre_positions[i] == check_val){
      Serial.println("Check Detected");
      digitalWrite(detect_led, HIGH);
    }
    else {
     digitalWrite(detect_led, LOW);
    }
    delay(30);
  }
  for(int i = 0; i <= 9; i = i + 1){
    Serial.print(pre_positions[i]);
    Serial.print(",");
  } 

  if (pre_positions[0] == check_val && pre_positions[1] == check_val && pre_positions[2] == check_val && pre_positions[3] == check_val && pre_positions[4] == check_val && pre_positions[5] == check_val && pre_positions[6] == check_val && pre_positions[7] == check_val && pre_positions[8] == check_val && pre_positions[9] == check_val  ){
    Serial.print(" - Pre Level Set");
    Serial.println("");
    delay(500);
    setlevel();
    delay(500);
  }
  else {
    Serial.println(" - No Set");
  }

}

//set all register pins to LOW
void clearRegisters(){
  for(int i = numOfRegisterPins - 1; i >=  0; i--){
     registers[i] = LOW;
  }
} 

//Set and display registers
//Only call AFTER all values are set how you would like (slow otherwise)
void writeRegisters(){
  digitalWrite(RCLK_Pin, LOW);
  for(int i = numOfRegisterPins - 1; i >=  0; i--){
    digitalWrite(SRCLK_Pin, LOW);
    int val = registers[i];
    digitalWrite(SER_Pin, val);
    digitalWrite(SRCLK_Pin, HIGH);
  }
  digitalWrite(RCLK_Pin, HIGH);
}

//set an individual pin HIGH or LOW
void setRegisterPin(int index, int value){
  registers[index] = value;
}

void writebargraph(int set, int led){
  if(set == 0){
    for(int i = 0; i <= 9; i = i + 1){
      if(i <= led){

        setRegisterPin(i, HIGH);
        writeRegisters();
      }
      else if(i > led){

        setRegisterPin(i, LOW);
        writeRegisters();
      }
     }
   }
  if(set == 1){
    for(int k = 10; k <= 29; k = k + 1){
      if(k <= 10 + led){
        setRegisterPin(k, HIGH);
        writeRegisters();
      }
      else if(k > 10 + led){
        setRegisterPin(k, LOW);
        writeRegisters();
      }
    }
  }

}

void setlevel(){

  int level0 = 0;
  int level1 = 0;
  int level2 = 0;
  int level3 = 0;
  int level4 = 0;
  int level5 = 0;
  int level6 = 0;
  int level7 = 0;
  int level8 = 0;
  int level9 = 0;
  int level10 = 0;
  int level11 = 0;
  int level12 = 0;
  int level13 = 0;
  int level14 = 0;
  int level15 = 0;
  int level16 = 0;
  int level17 = 0;
  int level18 = 0;
  int level19 = 0;
  int level20 = 0;
  int level21 = 0;
  int level22 = 0;
  int level23 = 0;
  int level24 = 0;
  int level25 = 0;
  int level26 = 0;
  int level27 = 0;
  int level28 = 0;
  int level29 = 0;

  int positions[30] = { level0, level1, level2, level3, level4, level5, level6, level7, level8, level9, level10, level11, level12, level13, level14, level15, level16, level17, level18, level19, level20, level21, level22, level23, level24, level25, level26, level27, level28, level29};

  digitalWrite(setlevelMode1_led, LOW);
  digitalWrite(setlevelMode2_led, LOW);  

  boolean seeking = true;

  while(seeking == true){
    for(int i = 0; i <= 29; i = i + 1){
      writebargraph(1,map(analogRead(0),20,600,0,19));
      positions[i] = map(analogRead(0),20,600,0,19);
      Serial.print(positions[i]);
      Serial.print(",");
      delay(10);
    }  

  if (positions[0] == positions[0] && positions[1] == positions[0] && positions[2] == positions[0] && positions[3] == positions[0] && positions[4] == positions[0] && positions[5] == positions[0] && positions[6] == positions[0] && positions[7] == positions[0] && positions[8] == positions[0] && positions[9] == positions[0] && positions[10] == positions[0] && positions[11] == positions[0] && positions[12] == positions[0] && positions[13] == positions[0] && positions[14] == positions[0] && positions[15] == positions[0]  ){
     Serial.print(" - Level Set");
     digitalWrite(setlevelMode1_led, HIGH);
     seeking = false;
   }

   else {
     Serial.print(" - No Set");
     digitalWrite(setlevelMode1_led, LOW);
   }

   Serial.println("");

  }

}

Here are some photos of the board if you want to try and work out the schematic:

PiPlanter 2 | Little Plants 1 / Germination Setup

The plants are coming along quite nicely, here is an album of images:

As for my grow setup in this stage, it’s pretty simple. Basically I keep the two desk lamps I have from that area on 24/7 and on the plants. Every morning I put about a half gallon into each of the trays. I also spray about 8oz onto the surface of the plants. Working pretty well so far, all of this growth is only after a week and two days.

PiPlanter 2 | Update / Dirt / Germs

Hi! In order to do PiPlanter 2 at the scale I want, as always, I need money. I’m applying to this grant to hopefully take this project to unreal new heights. In order to apply, one of the component is assembling a budget. In order to do that though, I need to “complete” the whole project… in my head. I have to be able to think of exactly how I want to do the project. From PCB design to pump system, I have to plan it all in order to assemble a realistic budget. There is a lot of good work that comes with this, like schematics and the budget itself. I’ll for sure upload all of the documentation.

On a more stimulating note: I’ve planted the tomato plants in the same manor that I did last summer and here are some pictures of the growth so far.

Here is the dirt and planted seeds:

Here are some very small sprouts that have developed in the last two days.

PiPlanter 2 | Getting Started Again

So I have decided to re write the PiPlanter from the ground up. In essence, it will accomplish the same exact thing but I’d like it to be a lot more of a stable platform to expand upon in the future. I’d also like PiPlanter to be professional enough to bring to market. First off there are a few things you’d need install & a few modifications you’d need to make to Raspian. First thing’s first, you’ll need to enable SPI in the kernel so:

sudo vi /etc/modprobe.d/raspi-blacklist.conf

Comment out the spi-bcm2708 line so it looks like this:

#blacklist spi-bcm2708

Then run this to make it more permanent.

sudo modprobe spi-bcm2708

Now for the real meat of it. You’ll need these packages for SPI and the WiringPi library makes things a whole lot easier for us. This program also relies very heavily

sudo apt-get install python-imaging python-imaging-tk python-pip python-dev git
sudo pip install spidev
sudo pip install wiringpi
sudo apt-get install apache2
sudo apt-get install mysql-server
sudo apt-get install php5
sudo apt-get install php5-mysql
sudo pip install tweepy</pre>
<pre style="color: #333333;">sudo pip install apscheduler</pre>
<pre>

Revised python code next post.

Raspberry Pi as a dedicated “Twitch Plays Pokemon” Viewer

Update: 12 October 2016

Thanks to commenter Fishscene for pointing out the following:

livestreamer for twitch is broken. Twitch made a change to require an OAUTH token and disallow annonymous viewing. livestreamer hasn’t been updated in over a year. Project was forked to streamlink and includes twitch fix:

https://github.com/streamlink/streamlink

I’ll leave this for prosperity, it has been linked to several time.

I’m not too proud of this but my laptop couldn’t handle streaming ‘Twitch Plays Pokemon’ and me doing day to day tasks and I can’t stop watching now. I’ve decided to use a spare Raspberry Pi have to keep the stream open 24/7 on a spare monitor I have.

Here’s a video:

Thanks to Livestreamer it is unbelievably easy to view this stream.

The following command will install Livestreamer:

apt-get install python-pip
pip install livestreamer

To make things even simpler, I have also written the following python program that will open the stream to HDMI. You can set the line that runs this program as a cron job to run at boot if you wish.

import os
os.system("livestreamer twitch.tv/twitchplayspokemon best -np  'omxplayer -o hdmi'")

Which you can get on your pi with:

wget https://esologic.com/source/TPP/raspberry_TPP.py

Once it is downloaded you can run it with:

python raspberry_TPP.py

And it will open on your HDMI monitor.

Server Upgrade | Migrating WordPress

Like I said in my first post for this server upgrade, a secondary purpose of this new server was to migrate my wordpress blog to a more stable server setup.

For my particular setup, I’ll be running my blog inside of a virtual machine running ubuntu 12.04 inside of a new server running ubuntu 12.04 as detailed in this post. This migration method does not care what kind of server you are using, so whatever setup you’re currently running should be fine.

The migration itself is remarkably easy thanks to a wordpress plugin called duplicator. Essentially the process is this.

On the old server, update wordpress and install duplicator. Go through the instructions listed in duplicator and save your files in a place where you can get them.

On the new server, install the latest version of wordpress and makes sure it is working 100%. You can use this guide if you need help doing that.

The only thing that stuck for me was the fact that after you finish the wordpress install, you need to run the following command.

chown -R www-data:www-data /var/www

This will give apache user permissions to write to disk.

Other than that, just follow the duplicator instructions.

Creating an Email Server at Home Inside of a Virtual Machine Using Linux & Citadel

Citadel makes this pretty sophisticated and money saving procedure really easy. Once I figured out what I was doing, the install took me about 45 minutes to complete, here are the steps I took!

I’m running PHPvirtualbox on ubuntu server 12.04 as detailed in this post.

First thing’s first, get a virtual machine with a debian based OS loaded up.

3

I’m using 12.04 for the VM as well

4

Then go through the OS install, only installing openssh-server as additional software.

5

6

First we need to give the server a Fully Qualified Domain Name (FQDN)

7

You will need to edit the

/etc/hosts
/etc/hostname

files.

8

Change whatever name you chose in the install process to ‘mail’ in the /etc/hostname

9

10

Modify your /etc/hosts as follows. The green box is the domain you will be using.

11

After rebooting, you will be greeted with a your hostname set to mail. You can still log in with your regular username & password.

12

Running

hostname
hostname -f

Should yield very similar results.

13

Now we need to establish a static for our virtual machine.

14

15

In PHPvirtualbox, set the network mode to ‘Bridged Adapter’

16

17

Running the following commands

hostname
hostname -f
ifconfig

And getting these results means our configuration is ready to go!

18

I am now using the Putty window so I can copy commands in. First log in as root.

19

Run

</pre>
apt-get install build-essential curl g++ gettext shared-mime-info libssl-dev
curl http://easyinstall.citadel.org/install | bash
<pre>

and go through the citadel install process.

20

21

22

23

24

25

26

27

28

29

30

I’m changing the default port to 80 for now, just for simplicity.

31

32

After the install, reboot the VM.

33

Now log in to citadel!

34

35

Now we need to do MX forwarding. My DNS host is network solutions, but the process is very similar regardless to which provider you use.

36

37

Again, your domain is represented by the green box.

38

39

The yellow box is your IP

40

41

You can use whatismypi to determine your IP address. If it is dynamic, you can use No-IP to get a static one .

42

43

The records should look something like this.

44

Now in citadel, you need to go to ‘Administration’ -> ‘Domain names and Internet mail configuration’ and add your domain.

45

Now open the following ports on your router. This is dangerous, but IMO worth it.

50

Now we test!

46

47

48

49

There we go! Pretty much no cost email addresses!

Thanks for reading, leave any improvements in the comments.

Server Upgrade | Citadel Install Inside of a Virtual Machine

Okay! So for now, I’ve landed on Citadel for the email server software that I’m going to use. I’ve bounced around between four different clients (iredmail, Citadel, Ubuntu’s Suite, and Zimbra) and have landed on Citadel because I can install it (lol) and because it suites my needs better. The other software suites are basically wrappers of a bunch of smaller discrete softwares that build up the Ubuntu Suite. This is fine for dedicated servers, but since I’m going to be running this inside of a Virtual Machine, it is more convenient for me to use Citadel.

The install is pretty simple once you get the prerequisites installed and prep the VM itself.

Since it’s a server, a static IP address on the network will be very useful. Setting the IP address of a Virtual Machine is surprisingly simple, or at least it is in my case.

You set the IP you want manually as done here, and to configure the VM you set the network to be attached to a bridged adapter as seen here:

To install citadel, run the following commands per the citadel install guide.

</p>

<pre>apt-get update
apt-get install build-essential curl g++ gettext shared-mime-info libssl-dev
curl http://easyinstall.citadel.org/install | bash</pre>
<p style="text-align: left;">

And the install should go off without a hitch. You can then navigate to yourserverip/mail to access citadel.