Reading analog values over I2C

So I’m back again with another I2C device made by NXP. My last one did I2C to SPI, but we’re here to do ADC.

Now, if you’re the average Arduino user, then you have 6 ADC ports on your Uno, so why would you need any more? Well, you probably don’t, but if you’re using an ESP8266, then the onboard ADC is kinda garbage as it only tolerates values up to 1V. For some devices, this may not work as they require or output values greater than that.

I’ll be using the NXP PCF8951. A quick search looks like it can be purchased in DIP form, but I’m using a SO-16 (SMD). From the datasheet, we have the following pinouts:

If you’re familiar with any I2C device, then a lot of these pins should look familiar:

  • The A0-A2 lines are to determine the address (it starts at 0x48 – 0x4F for Arduino).
  • Vss goes to GND and Vdd to +5v.
  • SDA goes to the SDA pin on the Arduino, and likewise for SCL.

For this example, we’re going bring all of the address lines to GND. Vref is pulled to Vdd, but this isn’t needed for this example as this will be ADC, but that’d be your max output value when converting a digital value to analog. The same goes for AGND, except this will be the corresponding GND (useful if you’re using this with a separate and unrelated GND).

EXT and OSC relates to using an oscillator. The datasheet says:

8.6 Oscillator
An on-chip oscillator generates the clock signal required for the A/D conversion cycle and for refreshing the auto-zeroed buffer amplifier. When using this oscillator the EXT pin must be connected to VSS. The oscillator frequency is available at the OSC pin. If the EXT pin is connected to VDD, the oscillator output OSC is switched to a high-impedance state allowing to feed an external clock signal to OSC.

For what we’re doing, we’ll just set EXT to low.

We’ll put two pull-up resistors on the SDA and SCL lines (as per usual). We’ll tie our non-used analog lines to GND (A1-A3).

Finally, for our actual device, we’ll connect our Analog Out to A0. In my case I’m using a cheap moisture meter (FC-28, for those playing alone at home), but you can use whatever you want. I’ve left it purposefully ambiguous in the circuit diagram.

Speaking of witch, if you have everything set up correctly, your breadboard should look like this:

Time to code!

I’m going to assume that you have the prerequisite libraries and such and don’t need an explanation on them. I’ll include that stuff in my code, but I won’t go in depth.

If we look at Figure 18 in the datasheet…hold on, I can’t harp on it how much you NEED to read the datasheet! Take my examples and use them to learn how to read the datasheet.

Anyway, if we look at Figure 18, we can figure out what commands we need to read from different values (or write them):

Since we just want to read from A0 on the chip, we’ll write 0x00 to the device from our Arduino. If you want to do A1, then you’d send 0x01, and so on. Now if all four of your analog ports have devices you want to read from, you can use the auto-increment flag and send 0x05 and read multiple times.

Anyway, here is the code as promised. It’s extremely short. As you run this, you’ll notice your max values might seem strange. For the answer why, you can easily find that in the datasheet. 😉


#include "Wire.h"
#define PCF8591 0x48

void setup()
{
Wire.begin();
Serial.begin(9600);
}

void loop()
{
int value = 0
Wire.beginTransmission(PCF8591);
Wire.write(0x00);
Wire.endTransmission();
Wire.requestFrom(PCF8591, 1);

value=Wire.read();

Serial.print(value);
Serial.println();

}

Posted in Engineering | Tagged , , , , | Leave a comment

TV Time! On the go! Part 1

Not too long ago, YouTube recommended this video to me about hacking a Sony Watchman:

I thought that was pretty neat and wondered what I could do with one, so I was able to pick one up for like $20, but if I just redid the experiment shown, then that would be boring and we may run out of those in the future. So instead, I purchased a Citizen Compact Pocket B&W LCD TV 06-TA (Which apparently cost $88!).

As we open this, we’ll see a TV tuner in there that we’ll want to remove. It is 10 pins and a pain in the butt to remove. I’ve highlighted the pins that connect to the tuner.

Now, with that removed, we can start looking at the good stuff! As mentioned in the above video, we have a MS1348FP on our board. Now, I didn’t go yanking it away, but I did experiment as shown below:

Now that we know this is the chip, we can remove it and (ab)use the datasheet and it’s pins for a composite out.

However, after removing it and hooking everything up, I found that composite video out isn’t quite right and has sync issues, so I’m going to have to come back with a follow up. 🙁

Posted in Engineering | Tagged , , , , | Leave a comment

Sennheiser HD 58X Jubilee Review via @Massdrop

Photo by grizzlybeast on Head Fi

Thanks to @PhillyD, I was told of a pair of Sennheiser headphones was available on Massdrop. They just came in and I thought I’d give my initial thoughts.

Now, if you want the fancy technical specs, then please see Head-Fi’s forums for more details. I’m going to be giving a light overview.

Appearance

First off, let’s look at appearance. These have a very “studio monitor” type look to them and certainly look more professional than say a pair of Beats by Dre. They have velvet cups which feel amazing on the ear. This is in comparison to leatherette on a lot of other earphones. That said, I expect them to get dirty quickly as a result of wear and use. If you’ve ever owned velvet anything, then you know that getting a stain in it is pretty much game over. The cans completely cover my ear and the top band isn’t that tight (helpful if you have a widehead or just don’t like your ears being squeezed). The top foam is in two parts, which is what it is.

Feel

How about feel? They feel like plastic. No way around that. These aren’t Meze’s. I feel like I could easily snap the plastic on the can near the cup, which might cause issues if you toss them in a backpack. It doesn’t feel fragile per se, but I think if I drop it a few times, then it’ll crack. The straps are steel. The edges could be smoother, but they aren’t sharp by any means. The included cable is heavy! I don’t see this as a bad thing as I’m sure we all have cheap earbuds where the speakers are good, but the cable breaks apart. The left and right lines have a diameter of 3mm (compared to the 1mm thickness on a pair of skullcandy ink’d). The headband feels sturdier, but I didn’t feel comfortable flexing it that much.

Sound

Finally, sound! Now I first have to admit my bias. I am not a fan of head massages (heavy bass). I feel like bass is easy to do and I look down on Beats by Dre for being glorified head massagers. I want to hear my vocalists and high range. Depending on who you ask, you might want to “burn in” your headphones (i.e. let them run with music playing for so many hours), but since I just got them, I haven’t gotten a chance to do that. I am listening to flac and wav files going through my desktops onboard soundcard (Audio device: Advanced Micro Devices, Inc. [AMD/ATI] SBx00 Azalia (Intel HDA) (rev 40)) without an amp or anything special:

Classical

How does Classical sound?

  1. CPE Bach’s Flue Concertos. It is a little heavy in the bass. I can hear the flutes, but they don’t stand out as much as I’d like.
  2. Likewise on Vivaldi’s The Storm Movement II.
  3. Verdi’s Requiem — Libre Me. Angela Gheorghiu’s vocals don’t stand out in Verdi’s Requiem and the midranges on sound muddled.
  4. Gregorio Allegri – Miserere mei, Deus. Quiet and that falsetto doesn’t ring like it should.
  5. Sarah Brightman — Pie Jesu. My last test is for the living angel Sarah Brightman’s Pie Jesu and I just don’t like the sound.

Jazz

What about Jazz? Well, I don’t own too many Jazz albums, but I feel it’s important to test.

  1. De-Phazz — Cut the Jazz. Sounds good, but a little too bass-y for me. Vocals sound like they should.
  2. Gotan Project — Celos. This is a beautiful song and really shows how good of a genre this can be. Again, heavy on bass, but warm vocals
  3. Lorenzo Trujillo & The Soul Circus. Could be brighter. Period.

Metal

Metal is a lovely genre because of how technical pieces can get. It tends to incorporate elements of classical which is always nice.

  1. Muse — Reapers. Snare and high hat sound like they are in a different room in the beginning. Vocals are fine.
  2. Deftones — Adrenaline Album. It’s okay. Nothing to write home about.
  3. Dream Theater — The Glass Prision. It’s okay.
  4. Dream Theater — The Dance of Eternity. I had to do this, because I’d get raked across the coals for not doing this Dream Theater classic. I was mostly interested in Ruddess’s Keyboard Solo. It didn’t pop like I wanted it to.
  5. Dan Mumm — Toccata and Fuge in D Minor. Guitar is muted by background instruments.

Punk

Punk is one of the genres that I listen to the most, so I better get some enjoyment out of here. 🙂

  1. Armor for Sleep — Car Underwater. Sounds right. Can’t complain.
  2. Chidos — Hey Zeus! The Dungeon. Everything is covered by the drums.
  3. Forgive Durden — Il Tango Della Signora Francesco di Bartolommeo di Zanobi Del Giocondo. Need more vocals.
  4. Fall Out Boy — West Coast Smoker. Patrick Stump’s voice seems to be in the sweet spot of these earphones.
  5. Paramore — crushcrushcrush. Haley sounds good, but the bass needs to drop.
  6. The Cab — One of THOSE Nights. The guitar stands out in an annoying way with it’s simple riff. This is something that I’ve never noticed in the song before.
  7. The Dear Hunter — The Color Spectrum Black EP. I heard some parts of the song that I’ve never heard before, so that’s neat!
  8. Jonny Craig — What I Would Give To Be An Australian. Someone who is in my vocal range. Good mixing by the studio and it is replicated here

Others

Any other music that I thought might be worth a listening to.

  1. Campo — Tuve Sol. Guitar strums sound very nice.
  2. The Reign of Kindo — Out of Sight Out of Mind. This is always awkward as you have a better sound quality on their YouTube Channel, so I decided to go with that instead of my own copy. A lot of the instrumentation can easily be heard and what I call a “Wall of Sound” isn’t as strong on a pair of modified headphones. Note, what I call “Wall of Sound” is different than the traditional definition, so sorry Beatles fans.
  3. Sergei Tumas — Libertango. The trumpet sounds nice and so does the synth.
  4. Josh Ritter — Another New World. The French Horns sound amazing! He voice stands out (like it should..)

Verdict

At $150, this is a good pair of earphones; however, I’ll certainly be getting some polyester filling to dampen the bass a lot. This is hands down my biggest complaint about it. They are a steal at sub $100, so check on eBay for second hand. They are leagues above what most people use, so my criticisms are not from the sub $50 range (most of what you find at WalMart or Target), so keep that in mind when reflecting on this review.

You can purchase them here (AFFILIATE LINK!)

Posted in Reviews | Tagged , , , , | Leave a comment

Catching up with the P8284A (quickie)

I have a few secret projects I’ve been working on, but a quick thing that I can show is how to make a working clock with a P8284A (Here is the datasheet)

This chip was used for generating the clock for 8086s and 8088s, so it’s kind of a big deal. The unfortunate thing is, they are hard to find nowadays.

If you are able to get your hands on one and want a quick and dirty way to set up one, then use the layout below:

or use this pdf.

Now wait! I hear you exclaim! You’re using a 24MHz to drive an 8088!? Those things can only handle a max of 8MHz and you’re supplying a crystal 3x as much!

Yes, this is true, but the P8284 outputs a signal 1/3 that speed. It’s wave output is a little weird too. Take a look:

Now I did make a board layout for it as shown below. The first image is of the front:

And here is the back:

I haven’t tested it, but I’m gathering a batch of boards to ship off to JLCPCB for further testing.

The giant circle in the middle is a mounting hole which should fit a m3 screw, but it might be too tight, we’ll see.

I won’t go in to too much detail about the various values I chose, but there are some “optional” parts (i.e. the capacitors). I don’t recommend skipping the timing (electrolyte) and bypass (ceramic) cap. You can get some more information on that here and other videos:

So maybe if you’re fixing your old IBM AT or IBM PS/2, then this might help 🙂

Posted in Engineering | Tagged , , , , , , | Leave a comment

Arduino I2C to SPI with SC18IS602B

I’m going to be doing some neat things with an STM32F030 and since it’s a limited pin number, I want to maximize my pins and I want to make it somewhat expandable\hackable, so because of this, almost everything is going to need to go across i2c; however, I have LCD screens that work across SPI and likewise SD cards can use a SPI interface, so I need a way to access those over SPI.

Enter the SC18IS602B! A relatively cheap I2C to SPI adapter and super easy to work with.

Setup

For our SPI device, I’m using Sparkfun’s Serial 7-Segment Display because of how basic it is. Just send it data and it’ll spit it on the screen.

Once you have it soldered to a breakout board, here is the layout I’ve gone with:

You’ll notice three lines going from 14-16 to ground. These are the address lines (A0 – A2 respectively). If you look in the datasheet (linked above) on Figure 4 we can configure the address for our device. Now if you’re new to I2C, then this is a very common feature of I2C devices.

For us Arduino users, we ignore the RW bit as that’s automatically taken care of by the Wire library, so all we need to do is look at the actual numbers, in our case, we are dealing with 0x28. So we would use

Wire.beginTransmission(0x28);

when we want to talk to that device. Of course, you can change the address lines yourself and change your corresponding variables. If you can’t figure it out, then the Arduino I2C Scanner Sketch is super useful.

First attempt

To talk to a specific SPI slave, then we simply do

Wire.beginTransmission(0x28);
Wire.write(0x0X);
Wire.write(DATA);
Wire.endTransmission();

Where X = the SPI slave number + 1 (yes, SPI slave 0 you would do Wire.write(0x01), see Table 4 for more information).

So, let’s write ‘hiEe’ to the display:

#include <Wire.h>

#define TWI_ADDR 0x28
#define RESET_SEG 7
#define RESET_TWI 8
void setup() {
// put your setup code here, to run once:

pinMode(RESET_SEG, OUTPUT);
pinMode(RESET_TWI, OUTPUT);
digitalWrite(RESET_SEG, HIGH);
digitalWrite(RESET_SEG, LOW);
delay(50);
digitalWrite(RESET_SEG, HIGH);

digitalWrite(RESET_TWI, HIGH);
delay(100);
digitalWrite(RESET_TWI, LOW);
delay(100);
digitalWrite(RESET_TWI, HIGH);
delay(1000);
Wire.begin();

}

void loop() {
// put your main code here, to run repeatedly:
Wire.beginTransmission(TWI_ADDR);
Wire.write(0x01);
Wire.write('v');
Wire.write('h');
Wire.write('i');
Wire.write('E');
Wire.write('e');
Wire.endTransmission();
delay(500);
}

Diagnosing the problem

We upload this and…..we get garbage!? Did we do something wrong? Is the chip broken? What’s going on?

We’ll let’s debug this using an oscilloscope. I’m using anOpenScope MZ and by probing the SPI Clock (Blue) and MOSI (Orange), I get this wave form:

Here, we can see our v and h being sent correctly, but we the screen is garbage…so what’s going on?

Well, sadly, the SparkFun datasheet doesn’t say this, but our problem is that we’re going too fast for the display to keep up with. So we must slow down our chip!

How though?

Fixing the problem

Well, time to turn to the Datasheet!

Section 7.5.1 gives detail on how to configure the SPI interface.

By default register 0xF0 is set to all zeros. If we look at bits 0 and 1, we can set the clock!

To do this, we’ll add the following:


Wire.beginTransmission(0x28);
Wire.write(0xF0);
Wire.write(0x03); //set our SPI clock to the slowest
Wire.endTransmission();

With this change and after we reupload, things should look correct, although, you may still see a flicker, but that can be adjusted to your own needs.

Now, I don’t know how a beginner is supposed to figure this out on their own (especially if they don’t have an oscilloscope), but I hope that this helps someone out.

Final Code

#include <Wire.h>

#define TWI_ADDR 0x28
#define RESET_SEG 7
#define RESET_TWI 8
void setup() {
// put your setup code here, to run once:

pinMode(RESET_SEG, OUTPUT);
pinMode(RESET_TWI, OUTPUT);
digitalWrite(RESET_SEG, HIGH);
digitalWrite(RESET_SEG, LOW);
delay(50);
digitalWrite(RESET_SEG, HIGH);

digitalWrite(RESET_TWI, HIGH);
delay(100);
digitalWrite(RESET_TWI, LOW);
delay(100);
digitalWrite(RESET_TWI, HIGH);
delay(1000);
Wire.begin();

//Slow down our SPI bus
Wire.beginTransmission(TWI_ADDR);
Wire.write(0xF0);
Wire.write(0x03);
Wire.endTransmission();

}

void loop() {
// put your main code here, to run repeatedly:
Wire.beginTransmission(TWI_ADDR);
Wire.write(0x01);
Wire.write('v');
Wire.write('h');
Wire.write('i');
Wire.write('E');
Wire.write('e');
Wire.endTransmission();
delay(500);
}

Posted in Engineering | Tagged , , , | Leave a comment

Foie Gras Mr. President?

Today was the day that many of us Americans had been waiting for: the big US-Russia summit in Helsinki, Finland.

This came off of a gaffe filled week while in the UK where the President insulted U.K. Prime Minister Theresa May in an interview with the Sun Newspaper, where he bashed her Brexit plan, encouraged Boris Johnson to be Prime Minister (although he didn’t say he should replace Ms. May), and said that the UK was in turmoil.

This comes after a tension filled NATO summit. Where he called on countries to pay more into their defense (which is fair), but wrongly stated that the US pays in excess 4%. He also stated that Germany is under control of Russia over the Nord Stream 2 pipeline, which Russia has turned off the gas to Ukraine.

The day before the meeting, President Trump sent out this tweet (which will play an important part later):

In today’s event, the president had a private meeting with Premier President Putin that lead to a press conference. In it, he took the position of Mr. Putin that Russia had nothing to do with the 2016 election meddling, contrary to what US intelligence says. Quoting:

REPORTER, AP: President Trump, you first. Just now, President Putin denied having anything to do with the election interference in 2016. Every U.S. intelligence agency has concluded that Russia did. My first question for you sir is, who do you believe? My second question is would you now, with the whole world watching, tell President Putin, would you denounce what happened in 2016 and would you want him to never do it again?

TRUMP: So let me just say that we have two thoughts. You have groups that are wondering why the FBI never took the server. Why haven’t they taken the server? Why was the FBI told to leave the office of the Democratic National Committee?

I’ve been wondering that. I’ve been asking that for months and months and I’ve been tweeting it out and calling it out on social media. Where is the server? I want to know where is the server and what is the server saying?

With that being said, all I can do is ask the question.

My people came to me, Dan Coates, came to me and some others they said they think it’s Russia. I have President Putin. He just said it’s not Russia.

I will say this: I don’t see any reason why it would be. But I really do want to see the server but I have, I have confidence in both parties.

I really believe that this will probably go on for a while but I don’t think it can go on without finding out what happened to the server. What happened to the servers of the Pakistani gentleman that worked on the DNC?

Where are those servers? They’re missing. Where are they? What happened to Hillary Clinton’s emails? 33,000 emails gone, just gone. I think in Russia they wouldn’t be gone so easily.

I think it’s a disgrace that we can’t get Hillary Clinton’s thirty three thousand e-mails.

I have great confidence in my intelligence people but I will tell you that President Putin was extremely strong and powerful in his denial today and what he did is an incredible offer.

President Trump spent more time focusing on attacking the DNC and Hillary Clinton than squaring up with Putin about what they did.

After the feedback the President tried to do some damage control with the following tweet:

After watching this, I felt genuinely upset and saddened by the actions the president took. To no surprise, Democrats took an attack at the President, which Chuck Schumer saying:

However, Republicans criticized him as well with House Speaker Paul Ryan saying:

“There is no question that Russia interfered in our election and continues attempts to undermine democracy here and around the world. That is not just the finding of the American intelligence community but also the House Committee on Intelligence. The president must appreciate that Russia is not our ally. There is no moral equivalence between the United States and Russia, which remains hostile to our most basic values and ideals. The United States must be focused on holding Russia accountable and putting an end to its vile attacks on democracy.”

Although Senate Leader Mitch McConnell was more careful in his wording:

The Russians are not our friends. I’ve said that repeatedly, I say it again today. And I have complete confidence in our intelligence community and the findings that they have announced

More statements can be found here.

One notable exception to the critique is Senator Rand Paul who said in part:

I’m not so sure I would describe it as siding with the Russians.

I would say that President Trump has healthy dose of skepticism towards our intelligence community. And I — I share some of that.

Today, the President tried to walk back these statements, and unfortunately many Republicans have bought into what was said; however, for me, it is too little too late. I believe the President said exactly what he meant and with President Putin playing with a soccer ball and dismissing everything as a kid’s game, I think it’s clear who won.

While some people may follow you blindly, I certainly won’t. You had two opportunities yesterday to clear things up (an interview with Sean Hannity and with Tucker Carlson) and did nothing. It wasn’t until you were on Air Force One that you tweeted saying he had confidence in our intelligence agencies, it wasn’t until the following day (when who knows how many countless advisers had to have smacked some sense into him) that he finally retracted it.

We tend to look at Jimmy Carter’s “General Malaise” speech as one of the worse moments in American history, but I think that this will now top it.

While you can tweet and rally as much as your want, you need to face it Mr. President, your goose is cooked.

Posted in Politics | Tagged , , , | Leave a comment

Seven Segment (Common ANODE) on Arduino

It feels like forever since I’ve posted! However, I have a very small post for beginners.

We’re going to use an Arduino to drive a single digit seven segment display. Why something so simple?
So this way we can build on this fundamental. This will also give a gentle introduction to reading datasheets.

Let’s start out with what we need:

  1. Arduino Uno (other variants will work, but for ease, I’m saying the Uno).
  2. A common anode seven segment. I’m using this one, but at the time of writing they are out of stock. Places like Digikey, Adafruit, and many other retails should have them if you search for those words.
  3. A 400Ohm Resistor (greater is OK)
  4. Our datasheet. If you can’t find one, then here is one.

Now, first things first: when we say common anode, we mean that it has a common “Vcc” rail[1]. This is opposed to our common cathode which means that each segment shares a “GND” rail.

Let’s take a look at our datasheet and open to page 2. Here we can see where Pin 1 is (lower left hand corner), how the segments are laid out, and how each segment works.

If we look at the following, we can see that we should provide pin 3 and 8 with our Vcc line:

Now if we look deeper into the data sheet, it says our MAX rating should be 2.5V. Now I could go into Ohm’s law (and I really should), but I’ll just say for 3.3V use a 400Ohm resistor. That said, 400Ohm is not a standard value. The closest is 390, which may burn out our 7-segment LED, so the next closest standard is 430Ohm which will work. To be completely honest, I’m using a 1KOhm resistor as I write this up, so don’t be “afraid” of not using the exact same value. 🙂

Let’s start out with just a “Hello World”. Connect your display as the following:

In this case, my 7-segment has the pins on the top and bottom and are five across. When we apply power, our segment should look like this:

Now if we compare this to our two images above, we can see that Segment E matches up with Pin 1. Likewise, you can take that wire on Pin 1 and turn on different segments.

Now with this done, we can write some Arduino code to count from 0 to 9 for us. To turn on multiple segments at the same time, just connect more segments to ground.

#define A 7
#define B 6
#define C 5
#define D 4
#define E 3
#define F 8
#define G 9

/**
 * Let's define what some numbers look like:
 * NUM | Segments on
 * -----------------
 *  0  | A,B,C,D,E,F
 *  1  | B,C
 *  2  | A,B,G,E,D
 *  3  | A,B,G,C,D
 *  4  | F,G,B,C
 *  5  | A,F,G,C,D
 *  6  | A,F,G,C,D,E
 *  7  | A,B,C
 *  8  | A,F,B,G,E,C,D
 *  9  | A,F,B,G,C
 */

/**
 * @brief turns off all of the segments
 */
void turnOffEverything()
{
  digitalWrite(A, HIGH);
  digitalWrite(B, HIGH);
  digitalWrite(C, HIGH);
  digitalWrite(D, HIGH);
  digitalWrite(E, HIGH);
  digitalWrite(F, HIGH);
  digitalWrite(G, HIGH);
}

void setup() {
  // put your setup code here, to run once:
  pinMode(A, OUTPUT);
  pinMode(B, OUTPUT);
  pinMode(C, OUTPUT);
  pinMode(D, OUTPUT);
  pinMode(E, OUTPUT);
  pinMode(F, OUTPUT);
  pinMode(G, OUTPUT);

  turnOffEverything();

}

void loop() {
  // put your main code here, to run repeatedly:
  for(int x = 0; x < 10; x++)
  {
    turnOffEverything();
    switch(x)
    {
      case 0:
        digitalWrite(A, LOW);
        digitalWrite(F, LOW);
        digitalWrite(B, LOW);
        digitalWrite(E, LOW);
        digitalWrite(C, LOW);
        digitalWrite(D, LOW);
        break;
      case 1:
        digitalWrite(B, LOW);
        digitalWrite(C, LOW);
        break;
      case 2:
        digitalWrite(A, LOW);
        digitalWrite(B, LOW);
        digitalWrite(G, LOW);
        digitalWrite(E, LOW);
        digitalWrite(D, LOW);
        break;
      case 3:
        digitalWrite(A, LOW);
        digitalWrite(B, LOW);
        digitalWrite(G, LOW);
        digitalWrite(C, LOW);
        digitalWrite(D, LOW);
        break;
      case 4:
        digitalWrite(F, LOW);
        digitalWrite(G, LOW);
        digitalWrite(B, LOW);
        digitalWrite(C, LOW);
        break;
      case 5:
        digitalWrite(A, LOW);
        digitalWrite(F, LOW);
        digitalWrite(G, LOW);
        digitalWrite(C, LOW);
        digitalWrite(D, LOW);
        break;
      case 6:
        digitalWrite(A, LOW);
        digitalWrite(F, LOW);
        digitalWrite(G, LOW);
        digitalWrite(E, LOW);
        digitalWrite(C, LOW);
        digitalWrite(D, LOW);
        break;
      case 7:
        digitalWrite(A, LOW);
        digitalWrite(B, LOW);
        digitalWrite(C, LOW);
        break;
      case 8:
        digitalWrite(A, LOW);
        digitalWrite(F, LOW);
        digitalWrite(B, LOW);
        digitalWrite(G, LOW);
        digitalWrite(E, LOW);
        digitalWrite(C, LOW);
        digitalWrite(D, LOW);
        break;
      case 9:
        digitalWrite(A, LOW);
        digitalWrite(F, LOW);
        digitalWrite(B, LOW);
        digitalWrite(G, LOW);
        digitalWrite(C, LOW);
        break;
    }
    delay(1000);
  }  
}

You'll hook it up like this:

Again, remember what was mentioned earlier. Also to note, that those are bends in the wire and not junctions and that I left Pin 5 (DP) unconnected.

You'll notice that to turn on a segment, we write LOW to it. Remember when we were switching things on by hand, we connected a segment to Ground to turn it on.

Anyway, upload it and watch your counter go from 0 to 9 and back over again.

If you want this code for yourself and you're too lazy to copy and paste, then here it is.

[1]: This is not 100% accurate, but it'll work for now.

Posted in Engineering | Leave a comment

Follow up to the Z08671-BASIC

Not too long ago, I talked about making a 6 chip basic computer with z8671.

I did finally do a layout and I’m going to have the board made by JLCPCB to see how they are. I was recommended them by @GreatScottLab, so if it’s horrible, then I’ll just blame him. 🙂

I know I said I could make a diagram, and I did. Here it is:

Posted in Engineering | Tagged , , , | Leave a comment

Working with stm8 in Linux

I was ordering some uCs a while back and I saw that the STM8 Discovery and decided to pick it up, because I needed something to get free overnight shipping.

I’ve recently decided to look at it again and thought I’d try my hands at programming it. I found this guide and followed it’s instructions, but I ran into this problem:


main.c:1:19: fatal error: stm8s.h: No such file or directory
compilation terminated.
main.c:1: warning 190: ISO C forbids an empty source file

Nota Bene: the discovery uses the stm8s and not the stm8l

So, I thought that was weird that it wouldn’t compile. I made sure to install the libs, so let’s see if we can find the header:


find / -name stm8s.h 2>/dev/null

but that turned up nothing…

Let’s try again:

find / -name stm8.h 2>/dev/null
#For those who are beginners and are wondering what I'm doing the 2>/dev/null
#it is because I don't care about files or directories I don't have access to
#for example /root/

This did turn up something, but:

/home/me/stm8flash/stm8.h

Which isn’t what we’re looking for…
Removing the #include statement only causes different errors.

Let’s take a look at something:


/usr/share/sdcc/include # ls
asm ds80c390.h limits.h pic16 stdbool.h stdnoreturn.h z180
assert.h errno.h malloc.h sdcc-lib.h stddef.h string.h
ctype.h float.h math.h setjmp.h stdint.h time.h
ds390 hc08 mcs51 stdalign.h stdio.h tinibios.h
ds400 iso646.h pic14 stdarg.h stdlib.h typeof.h

Oh…so there is no stm8s.h…Well, what does the part of sdcc source tree say? Answer: Nothing.

But wait a moment: lookie here: stm8.h

For right now, let’s just download it and compile with it..


sdcc -lstm8 -mstm8 --out-fmt-ihx main.c
stm8.h:176: syntax error: token -> 'machine' ; column 19

We are very close to solving this!

So it looks like the maintainer for this package might have goofed, but before we point the finger, let’s download the sdcc source and compile by hand:


svn co svn://svn.code.sf.net/p/sdcc/code/trunk sdcc-code #This takes a while, so only do this if you want to..

cd ./sdcc-code

./configure #I was missing gputils, so you may need that as well.

make -j $((2 * `nproc`)) #I recommend 2 * the num cpus you have although you can just run make, but it takes a while since there are so many PIC uCs to compile for..

sudo make install

Alright! Let’s give this a try:

/usr/local/bin/sdcc -lstm8 -mstm8 --out-fmt-ihx main.c

main.c:1:18: fatal error: stm8.h: No such file or directory
compilation terminated.
main.c:1: warning 190: ISO C forbids an empty source file


Damn!

Well, the install docs say to see sdccman.pdf (which of course sdccman.tex couldn't be found...) eventually I found myself on the sdcc wiki which referred me to this site and wouldn't you know it...they have a blinky LED as well; however, they aren't #include  or anything at all they just have a batch of defines at the top...lovely


// Source code under CC0 1.0
#include 

#define CLK_DIVR	(*(volatile uint8_t *)0x50c6)
#define CLK_PCKENR1	(*(volatile uint8_t *)0x50c7)

#define TIM1_CR1	(*(volatile uint8_t *)0x5250)
#define TIM1_CNTRH	(*(volatile uint8_t *)0x525e)
#define TIM1_CNTRL	(*(volatile uint8_t *)0x525f)
#define TIM1_PSCRH	(*(volatile uint8_t *)0x5260)
#define TIM1_PSCRL	(*(volatile uint8_t *)0x5261)

#define PD_ODR	(*(volatile uint8_t *)0x500f)
#define PD_DDR	(*(volatile uint8_t *)0x5011)
#define PD_CR1	(*(volatile uint8_t *)0x5012)


unsigned int clock(void)
{
	unsigned char h = TIM1_CNTRH;
	unsigned char l = TIM1_CNTRL;
	return((unsigned int)(h) << 8 | l);
}
void main(void)
{

	CLK_DIVR = 0x00; // Set the frequency to 16 MHz

	// Configure timer
	// 1000 ticks per second
	TIM1_PSCRH = 0x3e;
	TIM1_PSCRL = 0x80;
	// Enable timer
	TIM1_CR1 = 0x01;

	PD_DDR = 0x01;
	PD_CR1 = 0x01;

	for(;;)
		PD_ODR = (clock() % 1000 < 500) & 1;
}

So, adding those defines works. However, let's just copy the above code, compile it, and flash it:

stm8flash -c stlink -p stm8s003k3 -w stm8_main.c

And of course it works...

Now something VERY important is that there is a difference between the stm8 value line discovery and the stm8 discovery. They use different uCs and while compiling the code will be the same, using stm8flash won't. So if it seems to take forever to flash your device, then double check your chip (-p option).

In conclusion, it isn't the maintainer that goofed, but instead there is something strange with the original tutorial. Maybe Debian based distributions of sdcc include that header, maybe the author wrote it, but didn't list it, or who knows?

I'd suggest putting that into a header file so you can just include it in future projects. My goal is to take this device and make a Nokia 5110 display work with it. And before you ask, I haven't forgotten about the dash-cam project. I have most of the stuff done, I just need to do some additional writing to show how I got to where I got.

Now I am not a fan of the setup for stm8flash. I may submit a patch so everything is done "correctly" with ./configure, make, make install, but that's for a different time.

2018/01/08 UPDATE:

I've submitted a pull request. My forked repo can be found here

Posted in Computer Science, Engineering | Tagged , , | Leave a comment

Introduction to the M/M/1 Queue

For one of my projects, I needed to learn how to build an M/M/1 event simulator.

I thought I’d post this for everyone to see and perhaps this might help you if you’re in a Queuing Theory class.

Let’s start with an example:

You want to simulate how long it takes for people to checkout at a gas station. We assume that there is only one cashier and that anyone in the line stays in the line. The line is FIFO (First In First Out or First Come First Served). With this in mind, we’ve studied surveillance tapes and we realize that on average six people come in per hour. From monitoring register transactions, we know on average the cashier can check out eight people an hour.

There is a lot of information there. Let’s break it down and give ourselves some variables:

  1. Arrival Rate(λ): 6
  2. Service Rate(μ): 8
  3. Number of Cashiers: 1
  4. Queuing Style: FIFO

With all of these in mind, we can begin to work with our problem.

First thing that we need to assume is that arrivals and departures are exponentially distributed. How do we know this? I’ll mention it later, but you don’t even need to know what that phrase means right now.

With this information, we can decide the following information right away:

  1. Queue Utilization: λ/μ
  2. Probability that there are 0 customers in line: 1 – λ/μ
  3. Average Waiting Time: λ/(μ(μ-λ))
  4. Average Time Customer Spends in the gas station: 1 / (μ – λ)
  5. Average Number of Customers Spends waiting for service: (λ * λ) / (μ(μ-λ))
  6. Average Number of Customers in the station: (λ/μ) / (1 – (λ/μ))

Now these are all static numbers. How do we actually make a simulation?

Well, remember how we said this is a M/M/1 queue? Well the M stands for exponential distribution. So we can calculate if there is an arrival in a certain unit of time with the following equation:

Probability of arrival = λ*e^-(λ * t)

(Hopefully now the gears are starting to turn in your head on how to do this)

In this case, t stands for time. So if we want to know what is the provability of an arrival in 1 second in our above example, then we have

6 * e^-(6 * 1) = 14.87%

What is e? e stands for our Euler’s number which is the opposite of the natural log. So, ln(e) = 1. Don’t worry about that too much if you don’t get it, normally there will be a button on your calculator that puts in e for you.

If you take a random number generator and compare that with the probability of an arrival, then you can figure out if an arrival occurred.

So (in C):


float result = 100 * lambda * pow(M_E, (lambda * time)); ///M_E is our Euler's Number

odds = rand() % 100;

if(result > odds)
{
printf("Arrival occurred!\n");
}
else
{
printf("No Arrival occurred!\n");
}

Now that we’ve got arrivals, let’s handle departures.

We are going to use a very similar equation:

μ*e^-(μ * t)

See? isn’t that different at all. The trick here is that we want to keep looping until we get a departure, because otherwise our customer will be stuck in limbo and never be able to leave (and that means that no one else can leave as well).

In C:

time = 0;
while(1)
{
time++;
float result = 100 * lambda * pow(M_E, (lambda * time)); ///M_E is our Euler's Number

odds = rand() % 100;

if(result > odds)
{
break;
}
}

Here we keep looping until we get what we want.

Finally, we need to be respectful of who is in the line in front of us.

To do this, we need to have some sort of way to track when people enter the line and how long it takes for them to leave. While I did this using C++ and a vector, it could be done in C using a linked list and then finding when the last departure is. Some last bits of code are to follow.

Psudocode:

if(last_departure > arrival)
{
leave_time = last_departure - arrival + time_checking_out
}
else
{
leave_time = arrival + time_checking_out
}

Hope this makes things easier for someone else.

Code:
Click Here!

Posted in Computer Science | Tagged , , | Leave a comment