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

@Anicorn_Watch The Trio of Time “Hidden Time Watch”

Taken from their website

A while back I came across this Kickstarter for an interesting watch concept.

I looked at it, watched the video, decided to back it and was an “Early Bird”. Eagerly waiting, my watch finally came in over the weekend. It was promised in October, but if you really think any Kickstarter campaign will be delivered on time, then you are going to be very disappointed.

So, let’s talk about this watch!

The good:

  • Firstly I opted for a metal band and it is hands down one of the best bands I’ve ever had for a watch. It is very robust, easy to adjust, and it doesn’t take off all of your arm hair.
  • Next is the glass, the glass on here is very nice to look at and is claimed to be sapphire glass (I don’t have the means to test or verify this). I do think it’s going to last a long time and not crack easily. It has a nice smooth feel and I can’t detect any imperfections by running my fingers and nails over it

The bad:

  • I got the “rose gold” color, but as it sits in front of me, it doesn’t have the right sheen of rose gold and more of a blanched copper.
  • This watch sits at 1/3 of an inch (8.5mm or 6 pennies stacked on each other) thick and I think that is remarkably thick. I think it should be at least half that size. After opening up the back, it appears that there is a lot of wasted space.
  • Speaking of opening up the back, it is really simple. This could easily be some generic watch guts.
  • Finally, what I was really disappointed in was the movement. I was thinking there was going to be a solid purple disk and the hour hand was just going to be a moving opacity filter. This isn’t the case. It is a gradient disk going from purple to white and moves as one unit. Kind of boring and also kind of cheap. I’d also note that the pictures show the gradient extending well over 180 degrees, but on mine, while it does extend past that, it is effectively non-existent past 135.

Overall thoughts:

Am I sad or do I regret that I backed this campaign? No.

Did I overpay at $140 USD? Oh yeah. Knowing what I know now, I would say that this timepiece is worth $100 at most, but I’d say it shouldn’t be sold for less than $56.

Should you get one? At the retail price of $220 (which by the way is significantly less than what the Kickstarter stated…) then there are much better watches to buy. For example, this Seiko.

Numerical review? 3/10. The biggest problems are it’s price, hour hand, and generic guts. You can slap a designer’s name on it, but it is still just an average over-priced watch.

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

PIC Watchdog Timers

I’m an admitted newbie to PIC uCs, but I thought I’d share a quick thing I just ran into and it deals with the watchdog timer.

I recently purchased some PIC16F722A-I/SP from Arrow, because unlike the PIC16F877A, these don’t need an external oscillator crystal.

I wanted to play with this and I thought the best way was to just do a little “Hello World” type blinky-led.

So, here was my code (note, I use MPLab and xc8):


/*
* File: main.c
* Author: ceneblock
*
* Created on November 21, 2017, 12:30 PM
*/

#define _XTAL_FREQ 16000000UL

// CONFIG1
#pragma config FOSC = INTOSCIO // Oscillator Selection bits (INTOSCIO oscillator: I/O function on RA6/OSC2/CLKOUT pin, I/O function on RA7/OSC1/CLKIN)
#pragma config WDTE = ON // Watchdog Timer Enable bit (WDT enabled)
#pragma config PWRTE = OFF // Power-up Timer Enable bit (PWRT disabled)
#pragma config MCLRE = ON // RE3/MCLR Pin Function Select bit (RE3/MCLR pin function is MCLR)
#pragma config CP = OFF // Code Protection bit (Program memory code protection is disabled)
#pragma config BOREN = ON // Brown-out Reset Selection bits (BOR enabled)
#pragma config BORV = 19 // Brown-out Reset Voltage selection bit (Brown-out Reset Voltage (VBOR) set to 1.9 V nominal)
#pragma config PLLEN = ON // INTOSC PLL Enable bit (INTOSC Frequency is 16MHz (32x))

// CONFIG2
#pragma config VCAPEN = DIS // Voltage Regulator Capacitor Enable bits (All VCAP pin functions are disabled)

// #pragma config statements should precede project file includes.
// Use project enums instead of #define for ON and OFF.

#include

void main(void) {
TRISB = 0x00;
while(1)
{
RB0 = 1; // LED ON
__delay_ms(1000); // 1 Second Delay
RB0 = 0; // LED OFF
__delay_ms(1000); // 1 Second Delay
}

return;
}

The configuration bits I got from the IDE’s configuration bit configuration window (window -> configuration windows -> configuration bits).

So, ready to give it a go, I dropped it into my ZIF programmer, hooked up my PICKit 3 and everything went as it should! No Errors!

However, as I was watching the led flash on and off, I noticed that it wasn’t on for one second and off for another.

I tried adjusting the times in __delay_ms(), but that didn’t help. So I hopped on IRC and asked on freenode’s ##Electronics room. One of the users suggested that my problem was that I wasn’t clearing the watch dog timer before the delays.

So, I added in the following code:

asm("CLRWDT");

and now everything worked. That said, I could use this method or as the user suggested, I could extend the time before the watchdog timer resets. I might try that later, but this works.

This wasn’t my final solution though, while the inline assembly is just fine, I decided for this simple project I should just disable the watchdog timer all together, so changing the configuration bits:


#pragma config WDTE = OFF // Watchdog Timer Enable bit (WDT disabled)

Now everything is fine and dandy.

I’ll make a bigger project eventually, but for just right now, this is more than fine.

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

6-chip BASIC computer with Z8671

Taken from CPUShack (http://www.cpushack.com/2010/10/15/zilog-the-first-decade-z80-z8-and-the-z8000/)
I’ve had some Z8671 chips for a while and I wanted to build a BASIC computer (get it?).

I just wanted it up and running (for now) and I came across this Hackaday Post and related GitHub. I learned from the eevlog forum that there is an appnote, but despite it now being the third result on Google, I had trouble finding it at first. For future people, here is a link to it.

My first try was to follow the picture from SmallRoomLabs to get it up and running, and….nothing. At best, I got garbage (when using a 4MHz crystal) and more often than not, I got nothing.

So I put the project away and came back to it with similar failures.

The past few weeks; however, I really wanted to get it up and going. What did I do? I outsourced it to one of my lab mates. He was able to consistently get garbage out to the monitor. We tried different crystals, but never got it up and going.

The other night; however, I found the app note and saw the example setup listed. I forwarded it to my lab mate and he apparently had already found it, but wasn’t getting good results (he later said that he ignored the example setup).

Being aware of this, I decided to try to build it according to spec and go from there. One of the things that is in the sheet and (apparently) is extremely important is the crystal speed. It

    needs

to be 7.3728MHz. 4Mhz and 8MHz just don’t work.

I ordered the correct crystal from Arrow ( click here to see why I’m using them now) and it just came in.

I put in the correct crystal, adjusted my BAUD rate and there we go!

With that, I tried to play with some of the configuration.

I swapped out the crystal, but that took me back a few steps.

I adjusted the resistor location and that got me mixed results. I found out the best results were to have a pull-up resistor on P1_0 (pin 21) and that’s the minimum that you need.

I also didn’t have a 22pf capacitor, so using my capacitor rules, I put a 20 and 2pf in parallel. With it up and running, I tried to reduce the capacitance needed and found that I can just use it with 20pf.

For UART, I’m using an FTDI adapter that provides power and Serial I/O. The RX on the FTDI is going to the SO on the Z8671 (pin 4) and likewise the TX is going to SI (pin 5).

So, let’s do a chip count and the relevant pins:

  1. FTDI
    • Vcc -> Z8671 Vcc (Pin 1)
    • Vcc -> 1K Ohm Resistor
    • GND -> Z8671 GND (Pin 11)
    • GND -> 20pf
    • GND -> 20pf
    • TX -> Z8671 SI (pin 5)
    • RX -> Z8671 SO (pin 4)
  2. 20pf
    • pin 1 -> GND
    • pin 2 -> 7.3728MHz Crystal
  3. 20pf (yes 2)
    • pin 1 -> GND
    • pin 2 -> 7.3728MHz Crystal
  4. 7.3628MHz Crystal
    • pin 1 -> Z8671 XTAL1 (pin 3)
    • pin 1 -> 20pf
    • pin 2 -> Z8671 XTAL2 (pin 2)
    • pin 2 -> 20pf (the other one)
  5. Z8671
    • Vcc (pin 1) -> FTDI Vcc
    • XTAL 2 (pin 2) -> 7.3628 MHz Crystal
    • XTAL 2 (pin 2) -> 20pf (the other one)
    • XTAL 1 (pin 3) -> 7.3628 MHz Crystal
    • XTAL 1 (pin 3) -> 20pf
    • P1_0 (pin 21) -> 1K Ohm resistor
  6. 1 KOhm Resistor
    • pin 1 -> FTDI Vcc
    • pin 2 -> Z8671 P1_0 (pin 21)

I could have just drawn a diagram, but on page 4 of the application note, you have one there for you. If you want reset, then just put a jumper from pin 6 -> Ground to turn it off and disconnect (and connect to Vcc) to turn it on.

I feel kinda of stupid now that I see how easy this is, but that’s the way it goes. 🙂

I”ll probably hook this up to another uC so that I can have a pocket basic computer (similar to here ), but that is to be determined.

Posted in Engineering | Tagged , | 1 Comment

Quickie Problem with STM32F103C8T6

I just ran into a quick problem with my STM32F103C8T6 that I got to play with. Whenever I tried to upload code, I kept getting this error:


Error in initializing ST-Link device. Reason: No device found on target.

I know that I had my settings correct (using an ST-Link, SWD, and outputting to Intel hex format) and that the device was still alive since it was running other code; however, even when trying with a different programmer and reverifying the pins, nothing happened.

To fix this, I simply held down the reset button and as I hit upload, I let the button go.

This seems to have fixed the problem, but it is very strange. Anyway, I hope that someone else can benefit from this..

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