Friday, December 25, 2015

Bitcoin mining hardware for Christmas?

Since I was a teenager, I've been interested in cryptography.  I've also been interested in business and finance, and started my first business selling computer accessories in high school.  Bitcoin, as a crypto-currency, is something that certainly intrigues me.  Recently I decided to do some research on bitcoin mining.  It would seem there may still be opportunities for individuals to make money mining bitcoins.

The image above is of a Antminer S7, which today (Dec 25) sells for 2.91BTC.  One bitcoin is trading for about US$455, making the price of the miner about US$1325.  If you are willing to wait for the Jan 20th production batch, the price drops to 2.4BTC.  The only other bitcoin miner on the market at this time is the Avalon 6, which sells for 3.2BTC.  Rated at 3.65 trillion hashes per second (TH/s), the Avalon is much less powerful than the Antminer at 4.73 TH/s.

So can you make money with bitcoin mining hardware?  Probably, but it depends on where you live, or more specifically, what you pay for electricity.  It also depends on fluctuations in the bitcoin market including the price of bitcoin.  I'll explain my guess on where the market will go, and do the math on whether buying a S7 would be profitable where I live in Eastern Canada.

The first thing to work out is the landed cost of the S7.  Allowing about $50 for shipping and adding local taxes that would be due on import brings the cost up to $1575.  Adding three 500W power supplies (cheaper than a single 1500W supply) brings the total to $1725.  From there I could create a complex spreadsheet to calculate predicted mining difficulty increases and power costs, but it is a lot easier to use an online mining mining calculator.

The first field in the form is the difficulty increment, which I'll leave to the end as it is a bit complicated.  While the average cost of electricity in North America is close to 10c/kWh, where I live it is about 12c US, so 0.12 goes in the electricity price box.  I think the Antpool fees are less than 2%, but I left in the default 2% just to be safe.  The hash rate for the S7 is 4730 GH/s, and my previously-calculated hardware price was $1725.  Power consumption is around 1250W.  I expect it would take about a week from the time payment is made until the S7 would be up and running, so I put in 7 days for the start date.

Now for that complicated difficulty increment.  Although the form defaults to 20%, that is much higher than the average over the past year.  .To estimate the expected difficulty increase with a constant price, I looked at mid-February and mid-October 2015, when the price was about US$250/BTC.  The difficulty increase during that time was 30%, and averaged over the 17 difficulty adjustment intervals, that works out to 1.56%.  I rounded that up to 2%, in case the increase in difficulty in the future is slightly faster.  Based on those numbers, the S7 would start generating a profit in November of 2016.

Another complication to estimating mining profitability is the block reward halving that will likely happen by July 2016.  At that time the reward for mining will drop from 25BTC per block to 12.5BTC per block.  I suspect that will impact the economics of mining so that it would take about a year to start generating a profit instead of  about 10 months.

My conclusion from all this: If you bought yourself a bitcoin miner for Christmas, I think the odds are better than 50/50 that you'll make money on your investmentbet within 2 years.  Personally, I'd put my money in a low-risk investment that is likely to return 5-7%, or at least wait and see if the economics of bitcoin mining significantly changes.

2015/12/31 update

I just noticed the specs on the recent batches of S7s has changed.  The original specs were 4.86 TH/s using 162 chips (54 per board) running at 600Mhz and drawing 1210W with a 93% efficient PSU.  The chips were configured in 3 chains of 18 chips per board, running at 0.667V ea (12V/18).  The newest S7s now have 135 chips (45 per board) running at 700Mhz and drawing 1293W, generating 4.73TH/s.  This likely means there are 3 chains of 15 chips per board, running at 0.8V.  The higher voltage allows for a higher clock rate, but at the cost of power efficiency, going from 249W/TH to 273W/TH.

I suspect two reasons for the change.  The BM1385 chips (pdf datasheet) were not always stable running at 600Mhz, so Bitmain changed the default to 575Mhz on batch 2 and batch 4 (for 4.66 TH/s).  Running at a higher voltage allows the chips to run at a higher clock rate.  The second reason is probably cost reduction; they now can produce 20% more S7s than before for a given number of ASICs.  For the short term I think that is a good idea since the S7 is still the most power-efficient miner available.  Before more power-efficient equipment using 16nm mining ASICs starts shipping, it may make sense for Bitmain to make another version of the S7 with 4 chains of 20 chips per board running at 0.6V and 400Mhz.  The power consumption would be about 1000W for 4.8TH/s (208W/TH), and they would be more reliable running at lower voltages and cooler temperatures.

Sunday, December 20, 2015

$6 AD584KH voltage reference


After buying a couple cheap REF5050s that turned out to be no good, I decided to buy a $6 AD584KH voltage reference.  A new AD584 costs about $20, so getting a whole module for $6 may seem like a scam at first.  However a close look at the photos from the vendor, and the photo of the one I received reveal that the AD584KH used on these modules is not new.  The one I received has a date code of 9703, so these are used parts, likely de-soldered from old equipment.  For voltage references, used parts are usually better than new, because their stability improves after they are aged for 250-1000 hours.  References that are hermetically sealed in a metal can like the AD584 are even more stable than the REF5050 since changes in humidity do not reach the IC.  As can be seen from the calibration sticker on the anti-static bag, the output voltages were measured with a 6-digit bench meter.

The reference was useful for testing and calibrating my 2 auto-ranging meters.  I adjusted my old meter so that it now reads about 0.025% high on the 0-4V range.  My new meter doesn't have any calibration pots, but I was able to determine that it reads about 0.11% low on the 0-6V range.  I've also concluded that my Wing Shing TL431A parts are 2.5V, not 2.495.  This is not too surprising, as many other 431 parts are 2.5V, like the LT1431 and the CJ431.  I also checked a cheap 3-digit voltage meter, and found it was reading low by about 0.5%; not bad considering it costs not much more than a dollar.

Spending $6 to check a $25 meter is probably not something most people will do.  Although I don't need to be able to measure voltages down to the nearest millivolt, the perfectionist in me likes that kind of precision.  And with only occasional use, it is likely to maintain better than 0.01% (100ppm) accuracy for decades to come.

Thursday, December 17, 2015

Lightweight AVR assembler functions

Over the past few years, I've written a few posts about small problems in the way avr-gcc generates code.  These problems are typically poor optimization, and since they don't cause problems in program functionality, they tend not to be fixed.  I believe the biggest opportunity in optimization is in inter-procedure register analysis, which is being worked on in GCC 5, but is unlikely to support 8-bit AVR MCUs.  Therefore I have developed a lightweight ABI for calling assembler functions:

inline void eelog(char logdata)
{
    // no output, x register input, no clobbers
    asm volatile (
    "rcall eelog_\n"
    :
    : "x" (logdata)
    : );
}

Before explaining the above code, it helps to understand the standard avr-gcc register usage.  Functions are free to use registers r18-r27 and r30-31, which means that if the code the calls a function is using any of these registers, they need to be saved before calling the function.   This applies even if the called function doesn't even modify any of the registers, since the compiler doesn't do inter-procedure register analysis.  The following small program and assembler code shows what I mean:

void main(void)
{
    volatile uint8_t* ioreg;
    uint8_t offset = 0x3f;
    eelog(42);
    ioreg = (uint8_t*)0x0020;
    do {
        eelog(*(ioreg + offset));
    } while ( offset-- );
}

00000092 <main>:
  92:   cf 93           push    r28
  94:   8a e2           ldi     r24, 0x2A       ; 42
  96:   f4 df           rcall   .-24            ; 0x80 <eelog>
  98:   cf e3           ldi     r28, 0x3F       ; 63
  9a:   ec 2f           mov     r30, r28
  9c:   f0 e0           ldi     r31, 0x00       ; 0
  9e:   80 a1           ldd     r24, Z+32       ; 0x20
  a0:   ef df           rcall   .-34            ; 0x80 <eelog>
  a2:   c1 50           subi    r28, 0x01       ; 1
  a4:   d0 f7           brcc    .-12            ; 0x9a <main+0x8>
  a6:   cf 91           pop     r28
  a8:   08 95           ret

The compiler uses r28 for the offset counter, since the function being called is not allowed to use r28/r29 (aka the Y register).  Since r30/31 (Z) can be modified (clobbered) by the function, the Z register needs to be initialized each time through the loop (at 0x9a and 0x9c).  The single parameter is passed in r24.

Although I've been programming in AVR assembler for a few years now, it has taken me a while to learn inline asm.  I still prefer writing in plain asm, but inline asm is the only way I've found to call assembler functions from C without having to follow the standard calling convention.  The sample code at the start of this post defines a function named eelog that takes a single parameter passed in r26 (the low byte of the X register).  Using this technique, the compiler can safely use r24 for the offset counter instead of r28:
00000080 <main>:
  80:   aa e2           ldi     r26, 0x2A       ; 42
  82:   08 d0           rcall   .+16            ; 0x94 <eelog_>
  84:   8f e3           ldi     r24, 0x3F       ; 63
  86:   e8 2f           mov     r30, r24
  88:   f0 e0           ldi     r31, 0x00       ; 0
  8a:   a0 a1           ldd     r26, Z+32       ; 0x20
  8c:   03 d0           rcall   .+6             ; 0x94 <eelog_>
  8e:   81 50           subi    r24, 0x01       ; 1
  90:   d0 f7           brcc    .-12            ; 0x86 <main+0x6>
  92:   08 95           ret

A careful reader will notice that more optimal code would use r30 for the offset counter, but even recent versions of avr-gcc aren't that smart.  Given other examples of poor optimization have persisted for several years, it is unlikely avr-gcc will get as good as hand-written asm anytime soon.  Another thing sharp readers may notice is that the volatile keyword in the "asm volatile" statement is superfluous because asm statements that have no output operands are implicitly volatile.  I think it is best to leave it in, in case the function is later changed to have an output operand, or if it is used as a template for another function.

If anyone is wondering why I didn't make a simplified version of the the standard calling convention that just used r24/25, it is because there is no inline asm constraint for r24/r25.  The constraint "w" might get the compiler to use r24/25, but it also could use r26/27 (X), r28/29 (Y) or r30/31 (Z).

Conclusion

Using this technique can significantly reduce register pressure on the compiler, which will reduce code size and increase speed.  Inline asm constraints could also be used for a function that returns multiple values, without having to use a C struct.  Code can be found in my new avrutils repository.


Sunday, December 6, 2015

Piggy-prog release version


Over the past few months I've been making progress with piggy-prog and picoWiring.  Since the beta version of piggy-prog, I've made a couple changes.  The first is a 8Mhz clock on PD6 (Arduino pin 6) using PWM.  That pin connects to physical pin 2 of the AVR 8-pin AVR underneath, which is the clock in (CLKI) pin on the ATtinyx5 and ATtiny13.  This allows programming AVRs that (sometimes accidentally) have the fuse settings for external clock.

The second change I've made is to reduce the SPI SCK timing to 128kHz to allow for programming AVRs with the CKDIV8 fuse set (factory default).  According to the datasheet specifications a 250kHz clock should work, but a few ATtiny13s I tested required a 128kHz clock to work when the CKDIV8 fuse was set.

To build piggy-prog you can download piggy-prog.ino and upload it to a Pro Mini using the Arduino or Wiring IDE.  If you have avr-gcc and avrdude installed, you can download the release, and run "make avrdude" to compile and flash the code to the Pro Mini.  Plug the Pro Mini into a breadboard so pins 9 and 10 are 1 row below pins 4 and 5 of the ATtiny, and pins 5 and A0 are in the same row as pins 1 (RST) and 8 (VCC) of the ATtiny.  Power will be supplied by the Pro Mini, so no jumper wires are needed.

In addition to working with the ATtinyx5 and ATtiny13 MCUs, it should also work with the ATtiny2313.  Even though pin 4 is not GND on the tiny2313, the input clamping diodes will make the ground connection.  The diode voltage drop of about 0.7V will mean the power to the tiny2313 will be about 4.3V, but that is still well within the operating range of the chip.

For the next version of piggy-prog, I plan to add detection of the position of the attiny, so that if it is one row up or down on the breadboard, piggy-prog will indicate that the chip needs to be moved.  This detection will be done by putting a weak pull-up voltage on one of the pins and then detecting if the other pins go high.  Since the RST pin does not have a VCC clamping diode, it will also be possible to safely detect if  the chip is in backwards (where VCC and GND are swapped).  For version 1, pay attention to the position of pin 1 (with a round dot close to it), as it is possible (in theory) to damage both the Pro Mini and the target MCU if you put the ATtiny in backwards.  I have accidentally reversed VCC and GND on AVRs without any apparent damage, but YMMV.

Wednesday, December 2, 2015

NiMH battery discharge tests


A couple weeks ago my wife got a few ornamental Christmas trees lit by RGB LEDs.  Each of them takes 3 AA batteries,  I bought a pack of Amazon Basics batteries since they were the best deal I could find for good quality batteries, since they are OEM eneloop batteries.  The ones I received were manufactured 201412, which suggests they are 4th generation eneloops.  I used 3 of the Amazon Basics batteries in 2 of the trees, and 3 Rayovacs I had lying around for the third tree.  After the batteries ran out, I tested their voltages.  The Amazons were consistently in the 1V range, but one of the Rayovacs was completely drained, reading 0 volts, even after the 2nd fill charge/discharge cycle.  The three Rayovacs looked similar, but the 0V battery was a bit different than the other two.  After looking through all of my rechargeable batteries, I realized I had 3 different kinds; the "0V" battery shown in the top of the picture above, one labeled "pre-charged", in the lower part of the photo above, and a couple labeled "ready-to-use".  None of them had a capacity visible anywhere on the battery.

While I was confident that the capacity of the regular "0V" Rayovac was less than the "ready-to-use", I wanted to get a better idea of the actual capacity of the batteries.  I also have some 1st-generation eneloops "3UTG" I purchased over 5 years ago that I wanted to compare to the new Amazon Basics batteries.  I don't have smart battery charger/tester, but with a bunch of AVR boards around I thought it would only take a couple dozen lines of code to time the battery discharge.  Before I started, I decided to see if somebody had already made a battery discharge project I could use.  It didn't take long to find Denis Hennessy's battery capacity tester.  I'm not a fan of the Arduino core, but if it worked, it didn't matter much if the code isn't pretty.

After reviewing Denis' code, I determined it work work well with a couple small changes.  The AVR board I already had plugged into my breadboard was running at 3.3V, and Denis' code assumes an AVR running at 5.0V for the ADC calculations.  I changed the code to use a "VCC" define.  Even for boards running at 5V, using the exact voltage instead of assuming 5.0 could give more accurate ADC readings.  I also modified the code so the "test complete!" message is output to the serial log, since wasn't hooking up a 1602 LCD (the code works fine without the LCD or DS18B20 attached).  The last change I made was making the serial log output every minute instead of every second.  I connected a 3.7 Ohm (nominal 4 Ohm) 15W speaker in lieu of a power resistor, and single AA battery holder for the battery.

The 3.7 Ohm load means the discharge current will be in the 300-350mA range, which is a bit higher than typical battery-powered electronics projects, but still within manufacturer specs for AA NiMH discharge rates.  After a couple days, I had tested 5 different batteries:

The battery capacity tester calculates joules rather than mAh, so I've done a rough calculation in mAh since that is the typical rating for NiMH batteries.  The regular Rayovac (purple line) was about 1100mAh, with the pre-charged Rayovac (green line) around 1300mAh.  The ready-to-use Rayovac (red line) was around 1350mAh, which matches the capacity specified for the new Rayovac "recharge" batteries.  The 1st-generation eneloop is still doing pretty well at around 1900mAh, and the Amazon Basics give a very respectable 2050mAh.

My updates to the battery capacity tester were merged a couple days ago, so you just need to download the zip from Denis' github repository.  If you are not hooking up the temperature sensor, you can comment out the OneWire and DallasTemperature references.  You will need a copy of the Time library, which is now maintained by Paul Stoffregen.