tag:blogger.com,1999:blog-271417942024-03-13T13:42:23.589-05:00Dosch-man's BlogA good chopping block to expose my ideas, thoughts and most importantly document innovations, breakthroughs, studies and tips associated with anything technology related, along with any other flights off into the depths of humility, despair and egotism all pointed straight at society and all it's infamous devices of good, evil and otherwise.doschmanhttp://www.blogger.com/profile/00219948412523833756noreply@blogger.comBlogger49125tag:blogger.com,1999:blog-27141794.post-10188955103986607562018-04-24T21:54:00.001-05:002018-04-29T21:29:30.194-05:00Basement-Engineered Home Brewing Stirplate<br />
Although my outdated, neglected, who-gives-a-shit blog rarely gets posted to anymore, I have adopted a soft spot in occasionally 'giving back' and sharing to a focused community of DIY folks, especially in the home brewing world. This happens to be one of those moments.<br />
<div>
<br /></div>
<div>
I've been a very in-tune and serious-to-the-hobby home brewer for just over 3.5 years now. Much like anyone starting out, there is a metric ton of learning and process fine-tuning involved at a serious level, well beyond just making a remotely drinkable extract home brew. On top of that, it's a fucking money pit like any other hobby, but it also is the most collaborative and knowledge-sharing thing I've ever been a part of. From the just-starting-out brewer up to a seasoned Brewmaster at a brewery, anyone will talk 'shop' with you, give you pointers, and help you along the way. </div>
<div>
<br /></div>
<div>
For me, when cost-meets-process come into play, some will gladly pay for their home brewing solutions, while others try to DIY and/or re-invent the fuck out of the 'wheel of everything'. I feel like I'm right on the fence and just depends on my mood, ambition and if I feel like exerting my talent and time vs. making my checkbook a bit lighter out of pure convenience.<br />
<br /></div>
<div>
So what the fuck is this all about? It's about yeast cell generation and using a stirplate to perfect it.</div>
<div>
<br /></div>
<div>
I've always made 'shake when you walk by' non-stirplate yeast starters for years, and although many of the online tools for cell growth and propagation are slightly better-than-ballpark accurate, I felt like it was one of those core pieces of the brewing process I needed to improve to make/create a better fermented and consumable product, if not for any other reason, than for my own self preservation... and my kegerator.</div>
<div>
<br /></div>
<div>
In regards to stirplate topics as a whole, seems like most of us toying with this piece of equipment either have something already they aren't happy with, are in the market for one or simply not using one at all. Let's take the upper and lower extremes of these camps:</div>
<div>
<ul>
<li><b>Purchasing a $120+ Maelstrom stirplate from NB.</b> Some of us have disposable income to waste. I don't know a single person in our home brewing community who owns that thing except for one person <i>a friend of mine</i> knows. </li>
<li><b>12v PC fan with a random potentiometer hack off a voltage regular.</b> Mechanically and from an engineering point-of-view (I don't care how pretentious I come across as) --- not a real solution. Not to mention, it's shitty internet sheep plagiarism.</li>
<li><b>Legit, used lab-grade stirplate off an auction website.</b> This falls into the buy-it-the-fuck-already club. If there's anything I would respect and trust the most, it's this. But depending on the 'used' factor of this, it's not entirely out of the realm of getting a dud.</li>
<li><b>Buy a Stirplate kit.</b> There is but 1 or 2 real-deal engineered solder-yourself solutions I stumbled upon. One of which was archived and you couldn't buy it, the others were PC fan knock offs. However, it's just the kit --- you need to find the proper enclosure and rest of that jazz.</li>
<li><b>Stirplate is you.</b> As mentioned above and how I was doing all of this. I know friends who still do nothing more than agitate their still yeast starter over a period of 1-2 days when they walk by it and make way better beers than me. Absolutely legit.</li>
</ul>
</div>
<div>
But whatever avenue you go with, it's the same problems:</div>
<div>
<ul>
<li>They throw stir bars and often.</li>
<li>Linear variation in speed control is way more powerful than they need to be to make a vortex to draw in oxygen into wort solution while keeping yeast in suspension, but all the while, you still need that balanced power when considering, for instance, very large starters in 5000ml flasks.</li>
<li>The variable sweep of the speed you can dial for stirring (if that option exists) is not smooth and linear; it's pretty much on, slightly spinning or straight to 80,000,000,000 mph in a clockwise range of 6 to 3.</li>
<li>Some stirplates are under powered in the current department (if ran by batteries) so good luck making the minimum ~24h to double yeast cell rates because the draw off the DC motor will murder your battery in no time and you'll walk by a stirplate that isn't stirring anymore.</li>
<li>In regards to the stirplate being all about you, is that you get tired of babysitting that thing, forget to shake it, etc.</li>
</ul>
</div>
<div>
I like difficult problems and after pealing this back, and believe it or not: This wasn't the easiest problem to solve, let alone, solve correctly.</div>
<div>
<br /></div>
<div>
Now let's say you settled on making one yourself like I did. One thing I can attest to up front: for pure reference material, there is but maybe 2 or 3 legitimate pieces of content that even talk about electrical engineered home built stirplates on the ENTIRE internet. I've looked. And looked. And looked. I can't even find a good boilerplate schematic or circuit to work off of or get an idea going from. And anything I did find, I knew after 5 seconds of looking at it, there was no way that was working at all.<br />
<br /></div>
<div>
I think the biggest hurdle is turning all that Earth science and physics into a real electrical engineered solution. Even though this is NOT my wheelhouse what-so-ever, and I'm a mere hack EE hobbyist, I'm not naive to any of these things below that really mattered WAY more than engineering the right circuit design and parts IMHO:</div>
<div>
<ul>
<li>Magnetic field strength over distance to the non-competing polar magnetic source (e.g. stir bar) matters. </li>
<li>Increasing magnetic field strength with lower to super strong magnets and stacking and finding the right balance that balances well with gravity, water mass, the magnets in your stir-bar, while not adding too much torque stress on your motor.</li>
<li>The diminished effectiveness of magnetic pull between different layered materials such as pyrex, plastics, glass, whatever.</li>
<li>Centrifugal force in relation to the stacking, mounting and centering of the magnets over the shaft of the motor unit doing the spinning.</li>
<li>Calculating the proper duty cycle for the DC motor involved in the design so it receives the correct amount of 'kicks' (pulses) over a variable range that's seemingly very focused and linear.</li>
<li>Housing material for the stirplate itself can't compete or interfere with the magnets to be durable, waterproof, hold a flask of 2000ml or larger, and clearly, house the design footprint as well.</li>
<li>Gravity and mass of different volume levels of water and it's effect on stir bar (e.g. holding it down in relation to weight of the water and gravity over it), the increased torque on the motor that is needed to overcome and 'spin through it'.</li>
<li>Not lose sight of the fact that this thing needs to do what it was made for: agitate a solution with some spinning object, make a small vortex in liquid to pull in oxygen and do that task over and over for a long time. Basically: solve the problem without over-engineering the shit out of it.</li>
</ul>
</div>
<div>
I'm sure there's much more to say, and better eloquently put, too. But you get the point I'm trying to get across: there's a lot to consider and work through if you want to solve those problems above.</div>
<div>
<br /></div>
<div>
Without further ado, after almost 3 solid months of basement R&D, ripping shit off breadboards and starting completely over countless times, re-education in all that wonderful high-school level foundations in physics and Earth science that we all forgot eons ago, I bring you: a legit, working stirplate.</div>
<div>
<br />
<br />
<h4>
The Schematic</h4>
<div>
<br /></div>
Best part about this (to me) is it's a complete hardware PWM solution, 100% portable and reproducible. I'm very comfortable and skilled with AVR microcontroller development, but implementing a timer based PWM solution to create a duty cycle I can calculate already with some math on a 555 timer is a way easier re-build for <i>anyone else</i> who wants to create this. <br />
<br />
In the schematic, you'll see the use of an AVR, but it's just to use ADC to read the linear analog pot sweep that speeds/slow the duty cycle to the motor via the H-bridge IC and light up the LEDs in a seemingly eye-candy sort of way; it's totally optional and does nothing more than provide a visual reference of 'speed' beyond the potentiometer knob. Everything to the right of the dotted line "you need" to make this work. Everything to the left (e.g. AVR + LEDs), you don't. <br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEie3fcGrpbjzRGeCQDqNI6hCpEd0f9FuBCkYD2ViNSkTIBvpPaziGsXVVhfFMeDkXgfSLJSclHwhjNnHrm4ZRkKv-qmDR3iGPsqSjjshhyphenhyphenfUD2Vl_WydWqIwaXHpjzlmIaSeNtO/s1600/homebrew-stirplate-v1.0.jpeg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="1132" data-original-width="1600" height="60%/" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEie3fcGrpbjzRGeCQDqNI6hCpEd0f9FuBCkYD2ViNSkTIBvpPaziGsXVVhfFMeDkXgfSLJSclHwhjNnHrm4ZRkKv-qmDR3iGPsqSjjshhyphenhyphenfUD2Vl_WydWqIwaXHpjzlmIaSeNtO/s1600/homebrew-stirplate-v1.0.jpeg" width="60%" /></a></div>
<br /></div>
<div>
</div>
<br />
<div>
<h4>
The Parts List</h4>
<div>
<br /></div>
Some quick notes on the parts list. I had a hard time generating + exporting one with <a href="http://kicad-pcb.org/" target="new">KiCad</a> , so it's easier to just jot down some specifics of some of the parts that maybe need some explanation. ALSO, get the parts where you want. I'm listing where I got it, but I order from Amazon, Sparkfun, Adafruit, Jameco, Solar Robotics, and a handful of other places. <br />
<br />
<br />
<ul>
<li><a href="https://www.sparkfun.com/products/11696" target="_blank"><b>Sparkfun Hobby motor</b></a>: I bought a handful of these for a solar-powered motorized steampunk garden robotic project I was working on and had them lying around. The design lesson is: Don't go beyond the 3v boundary to drive these for a stirplate. Even though Sparkfun says "up to 12v", don't. From a current perspective, thing seems to need to sync about 450-500ma just to get going @ 3v.</li>
<li><a href="https://www.sparkfun.com/products/315" target="_blank"><b>SN754410 H-bridge</b></a>: I initially went down the path of trying to procure a L293D, but this was cheaper and was like-for-like on pinout. But it's output current is 1A. Yes, there are 'other' H-bridge ICs out there, but remember you need at least 500ma for that motor to start. That's why it was chosen.</li>
<li><b>5v VCC source</b>: I have a ton of old flip and pre-smart cell phone chargers around from my every-year-free-phone upgrades of the old days. Just pick something that's 5 volt DC and at least 850ma or higher. 1A preferable if you're going to use LEDs and microcontroller.</li>
<li><a href="https://www.sparkfun.com/products/526" target="_blank"><b>LD1117V33 voltage regulator</b></a>: Absolutely essential for driving the motor voltage source on the SN754410. Running the motor at 5v is too much; the more voltage, the higher the RPMs. However, you still need source 5v for the VCC power requirement of the 555 timer and the SN754410. I reference this, but I happened to have the older LD33V around that I used, but same thing.</li>
<li><b><a href="https://www.sparkfun.com/products/9273" target="_blank">555 timer</a></b>: As opposed to doing any PWM and duty cycle calculations with the AVR (which you can), I wanted to keep the stirplate as 'hardware' as possible. But see diode notes below this; the 50% duty cycle was just too much and I had to figure out a way to get lower than that.</li>
<li><b>1N4148 diode</b>: This was the crucial component. With a 555 timer, at best you can get 50% duty cycle with R1/R2 resistors. You can get lower if you put a diode across the pins. Since you're powering it with 5v, use the 1N4148. This <a href="https://electrosome.com/astable-multivibrator-555-timer/#Using_a_Diode_Parallel_to_resistor_Rb" target="_blank">calculator</a> was invaluable as well in enlightening me towards that path.</li>
<li><b>1k Linear Pot</b>: I used linear because I wanted it as smooth as possible. Unfortunately, I bought a super cheap Chinese potentiometer to save project costs and the sweep rate sucks on it. If you wanted to spend more money on a higher quality trimmer pot with more precise turn counts, do it. It'll only make it better, smoother and dial in speeds better. Don't do logrithmic --- you won't be happy and the growth ratios of speed up will NOT be what you want; you'll go from 0 to 80,000,000,000 mph as mentioned above.</li>
<li><b><a href="https://www.amazon.com/gp/product/B01EYQ1VTE/ref=oh_aui_search_detailpage?ie=UTF8&psc=1" target="_blank">5"x5"x4" enclosure</a></b>: I am glad that I happen to stumble upon this on Amazon. This worked out great and sized well with the array of Erlenmeyer flasks my friend let me borrow for testing. It's got a gasket on it for water-proofing, it's light but the plastic is super durable. Plus, the lid depth is not flush with the top of the enclosure, so it was easy to 'build up' magnets and the motor mount bracket to get just right.</li>
<li><b><a href="https://www.lowes.com/pd/Hillman-3-4-in-Ceramic-Disc-Magnet/3115767" target="_blank">Ceramic Magnets</a></b>: I used a combination of low-power and high-power magnets as explained above. I got mine at Lowes, but I'm sure whatever home improvement or hardware store has something similar. I used them as my base magnets because they had a bit more height than just using a rare earth or high-power magnet out of a spinning disk hard drive. There is a picture of this.</li>
<li><b>Hard Drive (neodymium) Magnet</b>: You totally need this, too, but just one of the two that you usually get when you tear open an old hard drive to get one. Just go find an old hard drive from a half-rate PC repair place in your city/town or if you have 8,000 sitting around like I do. And if you're really clueless, watch a <a href="https://www.youtube.com/watch?v=GQhSy-Kz5DM" target="_blank">Youtube video</a> how to get it out vs. brute forcing it like a cave man.</li>
<li><b><a href="https://www.hardwareworld.com/piru766/Mending-Brace-Zinc-3-x-5-8?gclid=EAIaIQobChMI2aK7w_nV2gIVS4GzCh2dUQEPEAQYBSABEgIUbfD_BwE" target="_blank">Stirplate Bar for Magnets</a></b>: This is just a 3" zinc mending plate I bought at a Menards or Lowes. I drilled into the center and just wedged it onto the motor shaft. Don't remember the drill bit diameter, but whatever the shaft was, I just got it 'right' so it snugged right on. Then the ceramic magnets were stacked correctly and epoxied on. The weight of this in combination with the magnets is 'about' right for the physics side of keeping the spinning smooth in check.</li>
<li><b>Motor mount</b>: That's just a 1/2" electrical conduit shaft thing I found in some junk pile in our datacenter at work that was being thrown out. The hobby motor perfectly fit in there. Then I just bought an "L" bracket and screwed it on and epoxied it as 90 degrees and straight as possible for extra stability. The motor can come out though --- remember if it burns out, I just want to replace the motor, not remake that whole thing again.</li>
</ul>
<div>
The optional parts (for the LED eye-candy):</div>
<div>
<br /></div>
<div>
<ul>
<li><b>ATMega168</b>: AVRs are my microcontroller of choice. I don't even use the Ardunio frameworks; just straight avr-gcc as my compiler. I could have used an ATtiny or something, but I want to ditch the LEDs and put on a 16x2 character display instead. So if I need to add it, I've already got the microcontroller with ample GPIO port pins to handle it, and it's a batter of just cutting out the display space on the enclosure and soldering it in. But whatever AVR you pick: you need at least 6 free GPIO pins for LEDs and it has to do ADC conversion to read the analog pot value and convert it to digital.</li>
<li><b>LEDs</b>: Some grab-bag shit I have around. I just picked colors of blue, the middle was yellow/green and the last one was red. I just put in nominal resistor values for blue and red because they were a touch brighter than my yellow/green ones, even though the voltage drop on those tells you otherwise. Don't read too much into that --- I just wanted the brightness to be visually 'even' between LEDs.</li>
<li><b>IC DIP sockets</b>: For the love of all things engineering, please solder in IC sockets in case you kill an IC or whatever, you pop it out vs. soldering it directly to your thru-hole board. We're talking mere pocket change here. I can remove the 555-timer, H-bridge or AVR (or upgrade them), especially the AVR; you'll be able to take it out, put it on your development board, write your new sketch, and pop it back in. </li>
</ul>
</div>
</div>
<div>
<br />
<h4>
AVR Code/sketch for ADC + LEDs</h4>
<div>
<br /></div>
Honestly, there isn't much to this. I spent way too much time monkeying around with ADC converted values from my pot, trying to create a fill-value map range just so it gave you a nice, visual "cute and smooth" light up pattern.<br />
<br />
Going back to my crappy Chinese potentiometer, a lot had to do with it's cheapness. I ended up taking up to 150 samples triggered off ADC interrupt, totalling and finding the mean, then creating a smaller linear map number value range.<br />
<br />
Here's what my ADC Interrupt routine looks like:<br />
<br />
<div>
<pre class="prettyprint" style="font-size: 10px;">ISR (ADC_vect)
{
trigger++;
if ( trigger < 150 ) {
ADCvalue += ADCH;
} else {
uint16_t mean;
mean = ADCValue / (trigger - 1);
sweep = map(mean, 0, 195, 4, 58);
ADCvalue = ADCH;
trigger = 1;
}
}
</pre>
</div>
Then in the main() loop, I just check the volatile global value of the ADC sample average of that window and have the LEDs turn on as the potentiometer value increases: <br />
<div>
<pre class="prettyprint" style="font-size: 10px;">while (1)
{
if ( sweet >= 67 ) {
// turn on all LEDs, adding final RED
} else if ( sweep >= 45 ) {
// Add in final Green/Yellow LED
} else if ( sweep >= 26 ) {
// Add in middle Green/Yellow LED
} else if ( sweep >= 14 ) {
// Add in first Green/Yellow LED
} else if ( sweep >= 12 ) {
// Add Green-only LED
} else if ( sweep >= 10 ) {
// Just Blue LED
} else if ( sweep >= 9 ) {
// Just Blue LED
} else {
// NO LEDs
}
_delay_ms(200);
}
</pre>
</div>
If you were to graph those values, they aren't exactly 'linear' either and look more exponential, but do notice how the values sit low then suddenly, it changes, and I'll chalk that naively (again) to using a cheaper grade potentiometer. My sweep really looked like this: <br />
<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjMhU_fr4dG-HVNLsOcKugenGhLQRbiKA7YvqKflxAnonvm1Qm_3xOh3yuTPs2u1zbBMGeLDqHqwbJWGyV1-CEWiJjGnSX9sWYhbTI681pZIEYVu5HbFf-M53oa8b3ygCKFlTPI/s1600/adc_sweep_vals.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="358" data-original-width="609" height="235" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjMhU_fr4dG-HVNLsOcKugenGhLQRbiKA7YvqKflxAnonvm1Qm_3xOh3yuTPs2u1zbBMGeLDqHqwbJWGyV1-CEWiJjGnSX9sWYhbTI681pZIEYVu5HbFf-M53oa8b3ygCKFlTPI/s400/adc_sweep_vals.png" width="400" /></a></div>
<div class="separator" style="clear: both; text-align: center;">
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<br /></div>
So even my map() function to convert on linear range to another smaller linear range wasn't evenly divisible at all, in terms of using the 'clock face' analogy that if your mapped range is 0 -60, dial is at 6 o'clock that 0, noon/12 o'clock should be 30 and almost back to 5/6 o'clock again would be 60; that's not the case. So I just played with the numbers until I felt it looked right when moving the knob from 'off' to 'full throttle': <br />
<br />
<br />
<div>
<pre class="prettyprint" style="font-size: 10px;">long map(long x, long in_min, long in_max, long out_min, long out_max)
{
return (x - in_min) * (out_max - out_min) / (in_max - in_min) + out_min;
}
</pre>
</div>
<br />
<br />
All that hard-coded nonsense I did was to just-get-it-done because it got to be a bit of an ass ache to do it differently so I opted for a short cut. I wouldn't use my numbers; that's going to depend a lot on the potentiometer you use. You'll just have to test your potentiometer, dump the values over USART (RS232) or write them to a character display, see what the base-10 value is, and make your own range. <br />
<br />
<div>
</div>
</div>
<div>
<h4>
The Pictures</h4>
<div>
<br /></div>
What kind of person would I be if I didn't put a metric done of pictures for you to scroll through and convince you to do it as well!<br />
<br />
Unfortunately, a lot of my video shots were iOS 'live photo' shots and found trying to use iOS Photo app to convert them didn't work at all out of the box. So I used <a href="https://itunes.apple.com/us/app/live-ly/id1085024470?mt=8" target="new">Lively</a> to convert them to animated GIFs quickly. They are absolutely amateur-hour and not great, but you get the point. <br />
<br />
<br />
<div>
</div>
<div>
<ul class="bxslider">
<li><br />
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi0lSnD6KMaRtxFxTc-Wzl7BWFlo1jvazwat4rx_b-9i1YhlOlLCUtjvVyE6Eq5SenR4ZtyUVoMPrC7B0sOOJGm04A9UGooIvNkhjLasiZxzq5zMAOGMomBlRY7O8h71WB3pDJ8/s1600/IMG_2068.JPG" imageanchor="1"><img border="0" data-original-height="1600" data-original-width="1200" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi0lSnD6KMaRtxFxTc-Wzl7BWFlo1jvazwat4rx_b-9i1YhlOlLCUtjvVyE6Eq5SenR4ZtyUVoMPrC7B0sOOJGm04A9UGooIvNkhjLasiZxzq5zMAOGMomBlRY7O8h71WB3pDJ8/s1600/IMG_2068.JPG" /></a><br />
</li>
<li><br />
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhT8gAylgPAfUMuNFw4jZz5cTwBvMLH1qF9ZkMdk4pjNkf2j1DEvJc8Q50CtHdfE4Lsz2dXg2jUEB1w4vpEocVf-x2NPIbPjB8q0ZmISPpnWd0xOxFudl4eS3416d_PuK-ZSD1q/s1600/IMG_8820.JPG" imageanchor="1"><img border="0" data-original-height="1600" data-original-width="1200" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhT8gAylgPAfUMuNFw4jZz5cTwBvMLH1qF9ZkMdk4pjNkf2j1DEvJc8Q50CtHdfE4Lsz2dXg2jUEB1w4vpEocVf-x2NPIbPjB8q0ZmISPpnWd0xOxFudl4eS3416d_PuK-ZSD1q/s1600/IMG_8820.JPG" /></a><br />
</li>
<li><br />
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjAyg9_AKxFmufr2ij00dDPHgAvZnP1oaoOP0-mPKoMpOxqLMNV0H91Wc_hiT37m_3RJY75R5CEXXm0IcrVTabW8p8fXp9hGvqcEQipolbtBloe7fwnrarktn7DSWxnXzRwbb3P/s1600/IMG_8823.JPG" imageanchor="1"><img border="0" data-original-height="1600" data-original-width="1200" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjAyg9_AKxFmufr2ij00dDPHgAvZnP1oaoOP0-mPKoMpOxqLMNV0H91Wc_hiT37m_3RJY75R5CEXXm0IcrVTabW8p8fXp9hGvqcEQipolbtBloe7fwnrarktn7DSWxnXzRwbb3P/s1600/IMG_8823.JPG" /></a><br />
</li>
<li><br />
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEggx8F9tWa4es4E25kDM7XZNxvfZptIIhy1Ci5v2-TurN5OUHwGQJCKhYY-JcBnhJdYeUXpwKT5oSxgxqBzsmZyZPLDoh2h1SrDWMvHtS-aGeLC00j5l__MOzRe2quUHoV6b-9_/s1600/IMG_8849.JPG" imageanchor="1"><img border="0" data-original-height="1600" data-original-width="1200" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEggx8F9tWa4es4E25kDM7XZNxvfZptIIhy1Ci5v2-TurN5OUHwGQJCKhYY-JcBnhJdYeUXpwKT5oSxgxqBzsmZyZPLDoh2h1SrDWMvHtS-aGeLC00j5l__MOzRe2quUHoV6b-9_/s1600/IMG_8849.JPG" /></a><br />
</li>
<li><br />
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiagLkSKcI2TO0p9uhYgu3b9EtNMzCTd40FvggK3uOhmTlgr76yNEGkmuJ6dIT-I4Roucsm_t2jpAsKjLWJyKua1md3hba5Ok-27-7TZCsllqLl-R97mdf6oGDdHlXe33TLI4Ip/s1600/IMG_8850.JPG" imageanchor="1"><img border="0" data-original-height="1600" data-original-width="1200" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiagLkSKcI2TO0p9uhYgu3b9EtNMzCTd40FvggK3uOhmTlgr76yNEGkmuJ6dIT-I4Roucsm_t2jpAsKjLWJyKua1md3hba5Ok-27-7TZCsllqLl-R97mdf6oGDdHlXe33TLI4Ip/s1600/IMG_8850.JPG" /></a><br />
</li>
<li><br />
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEilEcppljXRTdD6ybbJ3UiHNkPNPvb-kXrJ76NSMkq6NDw85T8wdg_3qvHr_0wJIj63tM1EZTrmPKtnbLH_ZWXQ6ykcBmqV3vS6l472D7CgiV07SAJ3Q0ZfWjNjv7DBW2MHmGzv/s1600/IMG_8851.JPG" imageanchor="1"><img border="0" data-original-height="1600" data-original-width="1200" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEilEcppljXRTdD6ybbJ3UiHNkPNPvb-kXrJ76NSMkq6NDw85T8wdg_3qvHr_0wJIj63tM1EZTrmPKtnbLH_ZWXQ6ykcBmqV3vS6l472D7CgiV07SAJ3Q0ZfWjNjv7DBW2MHmGzv/s1600/IMG_8851.JPG" /></a><br />
</li>
<li><br />
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiXSsZnRsZhkwHNZ19MjJmBkuStxT6edlEdLQUgET0Ual8m73Di8JHhOzFjxpUEt1m2Y9GXykrWFPd_Ez-SZX97I1IR4Jcajs6-jfSNMs7xEPMkhC-_F7F_RD3ZGkBPaYKkkHcL/s1600/IMG_8852.JPG" imageanchor="1"><img border="0" data-original-height="1200" data-original-width="1600" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiXSsZnRsZhkwHNZ19MjJmBkuStxT6edlEdLQUgET0Ual8m73Di8JHhOzFjxpUEt1m2Y9GXykrWFPd_Ez-SZX97I1IR4Jcajs6-jfSNMs7xEPMkhC-_F7F_RD3ZGkBPaYKkkHcL/s1600/IMG_8852.JPG" /></a><br />
</li>
<li><br />
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjZAb529CX6Fj31fB7Twdg49sRxD1ckxPkFElHW6OTvoKmto_3pDgca6x6Z7o7WMsGQe6oQxvmr_RrfJ_FBYR3CKn_PUPtf3oKkjLOvsMAdkv4ZXkcbTbYqLtNXG57uEH7z_r1X/s1600/IMG_8857.JPG" imageanchor="1"><img border="0" data-original-height="1600" data-original-width="1200" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjZAb529CX6Fj31fB7Twdg49sRxD1ckxPkFElHW6OTvoKmto_3pDgca6x6Z7o7WMsGQe6oQxvmr_RrfJ_FBYR3CKn_PUPtf3oKkjLOvsMAdkv4ZXkcbTbYqLtNXG57uEH7z_r1X/s1600/IMG_8857.JPG" /></a><br />
</li>
<li><br />
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhzcx1KRAnUZticHPT-E4Mqnc5UyOWCGW1AQt9FCPTzIEVQS7uOgNALpFfSETcdIfXjWRMsjM4jCt7MPxrzoFzjutn2_eWVzAUxdi_JwZxca-2QbNA_Gfv09ljZnvfmGQVPuGMa/s1600/IMG_8853.JPG" imageanchor="1"><img border="0" data-original-height="1600" data-original-width="1202" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhzcx1KRAnUZticHPT-E4Mqnc5UyOWCGW1AQt9FCPTzIEVQS7uOgNALpFfSETcdIfXjWRMsjM4jCt7MPxrzoFzjutn2_eWVzAUxdi_JwZxca-2QbNA_Gfv09ljZnvfmGQVPuGMa/s1600/IMG_8853.JPG" /></a><br />
</li>
<li><br />
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhXW2CpiU-W1PypsV8wSI0d03652hu0-7gBZ9p860L1NTkLq237SVdn48I4eJ6ZWRMlm3990b9yFzm4ro_fbm1QowGg4fzTUd4MjLRzxjWqM2On4GJVxCNTNFj2UvGG1PAk9O-S/s1600/IMG_8854.JPG" imageanchor="1"><img border="0" data-original-height="1600" data-original-width="1200" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhXW2CpiU-W1PypsV8wSI0d03652hu0-7gBZ9p860L1NTkLq237SVdn48I4eJ6ZWRMlm3990b9yFzm4ro_fbm1QowGg4fzTUd4MjLRzxjWqM2On4GJVxCNTNFj2UvGG1PAk9O-S/s1600/IMG_8854.JPG" /></a><br />
</li>
<li><br />
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgZcwEykO6jZKZnXuadfB9DX5DhEYq95SE1ZiJeB1BF5IuQ5VaXgpj89-bJWQ0OCMUl83afY2E4FMblkM9fhsx_hTuqOc6LmJMuxdRN89PubapUVMqa22xOaLZtD7LMIbLwLpsY/s1600/IMG_8855.JPG" imageanchor="1"><img border="0" data-original-height="1600" data-original-width="1201" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgZcwEykO6jZKZnXuadfB9DX5DhEYq95SE1ZiJeB1BF5IuQ5VaXgpj89-bJWQ0OCMUl83afY2E4FMblkM9fhsx_hTuqOc6LmJMuxdRN89PubapUVMqa22xOaLZtD7LMIbLwLpsY/s1600/IMG_8855.JPG" /></a><br />
</li>
<li><br />
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg4fMCUn4qdhHFibgXwgGpdAf9-fbiym-foBsPyBs8R-hZ87pD5ZZXqWWB5zSoBsFVgHCaVAuS7hxDp1omW15GZZe-IuLx9wTVZylCiBwyzhwxXPjGYOfNxa1nTYF8BjuywL4ww/s1600/IMG_8858.JPG" imageanchor="1"><img border="0" data-original-height="1600" data-original-width="1200" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg4fMCUn4qdhHFibgXwgGpdAf9-fbiym-foBsPyBs8R-hZ87pD5ZZXqWWB5zSoBsFVgHCaVAuS7hxDp1omW15GZZe-IuLx9wTVZylCiBwyzhwxXPjGYOfNxa1nTYF8BjuywL4ww/s1600/IMG_8858.JPG" /></a><br />
</li>
<li><br />
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgQmSIR4gGMrfM7thSbA4NE9bxbAlk1AdwfHz9BGRWle7d8xJcitGcOjblIOE1yIm16E0FSVriTxpVH4aMbsFK34NNxRWUiI6RRNJq7sRGiDregrHvgdTQHfNVSGU2Oidwcayqa/s1600/IMG_8859.JPG" imageanchor="1"><img border="0" data-original-height="1600" data-original-width="1200" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgQmSIR4gGMrfM7thSbA4NE9bxbAlk1AdwfHz9BGRWle7d8xJcitGcOjblIOE1yIm16E0FSVriTxpVH4aMbsFK34NNxRWUiI6RRNJq7sRGiDregrHvgdTQHfNVSGU2Oidwcayqa/s1600/IMG_8859.JPG" /></a><br />
</li>
<li><br />
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjGTC3s_YvP8pZ5KXf2cS5EZaUIEGUf5MwGUxDn8uJRHVGBrSg4hBnCEqGRqtk6O2nLLxWcsWFFbyWrJ7E_kqciSwdK4A3KDjCJ4MrGZ9UGMeaVVcL79x3n0Jt2gOPjLz7GWgrk/s1600/IMG_8860.JPG" imageanchor="1"><img border="0" data-original-height="1600" data-original-width="1200" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjGTC3s_YvP8pZ5KXf2cS5EZaUIEGUf5MwGUxDn8uJRHVGBrSg4hBnCEqGRqtk6O2nLLxWcsWFFbyWrJ7E_kqciSwdK4A3KDjCJ4MrGZ9UGMeaVVcL79x3n0Jt2gOPjLz7GWgrk/s1600/IMG_8860.JPG" /></a><br />
</li>
<li><br />
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhTnoqpqp__DeKXdFONA6Czv80n3RA41tfCu1nzoykCoPc6M7cDEGCf7LlB9aPJjtJjVdcDVSfkeBP4zpXt1vwWGSdZAh4jQvUEb30AeM8AKuCsbfV-S6OAIOhQ63RMyTxpyZqG/s1600/IMG_8861.JPG" imageanchor="1"><img border="0" data-original-height="1600" data-original-width="1200" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhTnoqpqp__DeKXdFONA6Czv80n3RA41tfCu1nzoykCoPc6M7cDEGCf7LlB9aPJjtJjVdcDVSfkeBP4zpXt1vwWGSdZAh4jQvUEb30AeM8AKuCsbfV-S6OAIOhQ63RMyTxpyZqG/s1600/IMG_8861.JPG" /></a><br />
</li>
<li><br />
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiGnJosb3sEDyhyphenhyphenBAZ0qICeFrfIZbU0XwyXnze_gkEOfAmsVKMd_sZVMGFikqMpKiA9pO5hn-taVEQhtCjH2V7n4nwMuuT0NhnqADMd4eO2zy02MgsNr0WZKBZfRYP3kNQi_YNu/s1600/IMG_8862.JPG" imageanchor="1"><img border="0" data-original-height="1600" data-original-width="1200" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiGnJosb3sEDyhyphenhyphenBAZ0qICeFrfIZbU0XwyXnze_gkEOfAmsVKMd_sZVMGFikqMpKiA9pO5hn-taVEQhtCjH2V7n4nwMuuT0NhnqADMd4eO2zy02MgsNr0WZKBZfRYP3kNQi_YNu/s1600/IMG_8862.JPG" /></a><br />
</li>
<li><br />
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgVKFmgoU-KuJKRYev4uHirWk4B9lcFdbf1HH8WALQnX4r3LzNh_sHZRK1BSpvPtUovwm0jhKmoZsbzHLRfaDC2rLJ2K7i1q3QAq3-iPB8uoFJnneK6vT_s8OmRK3EVqzJjImpL/s1600/IMG_8863.JPG" imageanchor="1"><img border="0" data-original-height="1200" data-original-width="1600" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgVKFmgoU-KuJKRYev4uHirWk4B9lcFdbf1HH8WALQnX4r3LzNh_sHZRK1BSpvPtUovwm0jhKmoZsbzHLRfaDC2rLJ2K7i1q3QAq3-iPB8uoFJnneK6vT_s8OmRK3EVqzJjImpL/s1600/IMG_8863.JPG" /></a><br />
</li>
<li><br />
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgPr3CQIQm8YsrTtqvPLUEhZQWLaY4eTp2I7YCJ8qCbgigUOjcRP0Qmf0MUox9ndgNji2iKja7eqaVig0yMIjr9wz18VPF_-Ylnk8_UnPutWLlg_BjVe1SVrONk8OuwNceYI4AK/s1600/IMG_8873.JPG" imageanchor="1"><img border="0" data-original-height="1600" data-original-width="1200" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgPr3CQIQm8YsrTtqvPLUEhZQWLaY4eTp2I7YCJ8qCbgigUOjcRP0Qmf0MUox9ndgNji2iKja7eqaVig0yMIjr9wz18VPF_-Ylnk8_UnPutWLlg_BjVe1SVrONk8OuwNceYI4AK/s1600/IMG_8873.JPG" /></a><br />
</li>
<li><br />
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi8D_1DO5vpIlF0152X-_1s5P_WJ4dwiE6GGacVec8JQWd81OkQ7evOXwHz0V9gOSWfoGfYaYzp1tmP8ThAIorGcUqbj90nChJqlDGmF-Df8khxnCmtQzWwHU1HUn6Z7UdQGxFK/s1600/IMG_8874.JPG" imageanchor="1"><img border="0" data-original-height="1600" data-original-width="1200" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi8D_1DO5vpIlF0152X-_1s5P_WJ4dwiE6GGacVec8JQWd81OkQ7evOXwHz0V9gOSWfoGfYaYzp1tmP8ThAIorGcUqbj90nChJqlDGmF-Df8khxnCmtQzWwHU1HUn6Z7UdQGxFK/s1600/IMG_8874.JPG" /></a><br />
</li>
<li><br />
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjKHFH_PeM7D5rk95NAedxlFo9yn4r12HEabFmnBrxyhTdW0io-riBAMpWsMBEcanVUN6JNHV1vdOA97toM0359Up-Q_PvreVG-JnCkt4rkWHccg_DXK1nZos1IvbaR19N93Ll5/s1600/IMG_8875.JPG" imageanchor="1"><img border="0" data-original-height="1600" data-original-width="1200" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjKHFH_PeM7D5rk95NAedxlFo9yn4r12HEabFmnBrxyhTdW0io-riBAMpWsMBEcanVUN6JNHV1vdOA97toM0359Up-Q_PvreVG-JnCkt4rkWHccg_DXK1nZos1IvbaR19N93Ll5/s1600/IMG_8875.JPG" /></a><br />
</li>
<li><br />
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgAYwHkgklDp9SNRAIQvtqgAspZ0TAQF3PaFBjyyrerTJA_payeumS7GtstoCn9HcE7cQ1oqaNhktHOaQzA3FwzPwHGURvDqwtCfvNOM-hKYyxAp9o8tqATFwGGOkBnwDIO79CX/s1600/IMG_8876.JPG" imageanchor="1"><img border="0" data-original-height="1600" data-original-width="1200" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgAYwHkgklDp9SNRAIQvtqgAspZ0TAQF3PaFBjyyrerTJA_payeumS7GtstoCn9HcE7cQ1oqaNhktHOaQzA3FwzPwHGURvDqwtCfvNOM-hKYyxAp9o8tqATFwGGOkBnwDIO79CX/s1600/IMG_8876.JPG" /></a><br />
</li>
<li><br />
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgcyvJsLnQ16kCiiiVI-w3ebZO3ssv52gNBnzl_wPc3-R-goVgfNgomyiywiafaA6OVCDStBh0z6GI-vPipkuCN21K1SK_3PBjp7PaRnZJFDgwd_ntBX9CcQ9IaeWY6wBv6NLIk/s1600/IMG_8877.JPG" imageanchor="1"><img border="0" data-original-height="1600" data-original-width="1200" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgcyvJsLnQ16kCiiiVI-w3ebZO3ssv52gNBnzl_wPc3-R-goVgfNgomyiywiafaA6OVCDStBh0z6GI-vPipkuCN21K1SK_3PBjp7PaRnZJFDgwd_ntBX9CcQ9IaeWY6wBv6NLIk/s1600/IMG_8877.JPG" /></a><br />
</li>
<li><br />
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgR5Qr14nBuyJudUcBBsowczFXrQ2a-PWuLLWzzA8B-nArO8Tv-pMVhxLs0vxmww_VrLHAYS-_ayeQl3Kg_FZNNl_r-U-HI27qSvjz2DftjdkRaICD-N-ORKGH3YMHucGM4myWZ/s1600/IMG_8878.JPG" imageanchor="1"><img border="0" data-original-height="1600" data-original-width="1200" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgR5Qr14nBuyJudUcBBsowczFXrQ2a-PWuLLWzzA8B-nArO8Tv-pMVhxLs0vxmww_VrLHAYS-_ayeQl3Kg_FZNNl_r-U-HI27qSvjz2DftjdkRaICD-N-ORKGH3YMHucGM4myWZ/s1600/IMG_8878.JPG" /></a><br />
</li>
<li><br />
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjCoA2v9n_ispwyWgJec9K-1XpEjzIFFDvV0htXWw7t0uNvTq7RF-RZ-c4uevq19BNvPoN5LDtrzElraUzKEUG2nUB40fxuwm-PSx82SwAuGIozf-kKDb2NowQUkv0ntIeA_YaC/s1600/IMG_8879.JPG" imageanchor="1"><img border="0" data-original-height="1600" data-original-width="1200" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjCoA2v9n_ispwyWgJec9K-1XpEjzIFFDvV0htXWw7t0uNvTq7RF-RZ-c4uevq19BNvPoN5LDtrzElraUzKEUG2nUB40fxuwm-PSx82SwAuGIozf-kKDb2NowQUkv0ntIeA_YaC/s1600/IMG_8879.JPG" /></a><br />
</li>
<li><br />
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh-3ND0GYoVgzVFFDCpFOMNg4nrs0dwBHaz055GXNpQmbj4ouVxSNzAU0z_e16F2esPzzUJhi36Hk91o20XXHEYPhhl2wyUCKwLchecbLiuboPCw_XvLj_E2mVxd_HkYRFQ9gj1/s1600/IMG_8881.JPG" imageanchor="1"><img border="0" data-original-height="1600" data-original-width="1200" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh-3ND0GYoVgzVFFDCpFOMNg4nrs0dwBHaz055GXNpQmbj4ouVxSNzAU0z_e16F2esPzzUJhi36Hk91o20XXHEYPhhl2wyUCKwLchecbLiuboPCw_XvLj_E2mVxd_HkYRFQ9gj1/s1600/IMG_8881.JPG" /></a><br />
</li>
<li><br />
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiS6iCWDlX1w65IDAdx32s1fFmSPr5VCSHzDVOrori2c4lRKjvHM774n9J_Om527B90oD4msBK6Ue4SgKK_z_jhkzrcg3LjsQ5KZX0sN_6KCF9_0fRwMPP7OJAVhdTw5TX4UlEp/s1600/IMG_8882.JPG" imageanchor="1"><img border="0" data-original-height="1600" data-original-width="1200" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiS6iCWDlX1w65IDAdx32s1fFmSPr5VCSHzDVOrori2c4lRKjvHM774n9J_Om527B90oD4msBK6Ue4SgKK_z_jhkzrcg3LjsQ5KZX0sN_6KCF9_0fRwMPP7OJAVhdTw5TX4UlEp/s1600/IMG_8882.JPG" /></a><br />
</li>
<li><br />
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiNknNpcoroNE39-L4M9p3Uxp1BXx8TtIUxpgtXDQq6wcODT4Fgg7ssBJxbZ7LK4ygXwxnS7hL0fZxxdHheYZLrZb1XoBgW9u5PCIAnXiWFfxVcDNjEXbffzX88GiyjtlmfHI0K/s1600/IMG_8883.JPG" imageanchor="1"><img border="0" data-original-height="1600" data-original-width="1200" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiNknNpcoroNE39-L4M9p3Uxp1BXx8TtIUxpgtXDQq6wcODT4Fgg7ssBJxbZ7LK4ygXwxnS7hL0fZxxdHheYZLrZb1XoBgW9u5PCIAnXiWFfxVcDNjEXbffzX88GiyjtlmfHI0K/s1600/IMG_8883.JPG" /></a><br />
</li>
<li><br />
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjR58J6MsMzNW2fC2BQyMgxcMQtMJPZDUfqMr0FZTxkN7pZlM_7SjQLHIfAeIr8icnlKJWj-UCVTnEs6su4qzJUi4Wh1Zgu8_tO6NG51RnLLfraIeDXNcitS-xuXYX1XdzB693N/s1600/IMG_8884.JPG" imageanchor="1"><img border="0" data-original-height="1600" data-original-width="1200" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjR58J6MsMzNW2fC2BQyMgxcMQtMJPZDUfqMr0FZTxkN7pZlM_7SjQLHIfAeIr8icnlKJWj-UCVTnEs6su4qzJUi4Wh1Zgu8_tO6NG51RnLLfraIeDXNcitS-xuXYX1XdzB693N/s1600/IMG_8884.JPG" /></a><br />
</li>
<li><br />
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjYs0wOTZu3FvFTngRutpuN1gSN2UDqTACAxCtdIRHrH5vUaRJqSSL7Phy_1TxYr7_fsjr1V8icezholBZMn1N3r8EQKnvhDcc4pEIww_q4eCf1Dz5RqYMB4gZAlQrBZXysVTlV/s1600/IMG_8885.JPG" imageanchor="1"><img border="0" data-original-height="1600" data-original-width="1200" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjYs0wOTZu3FvFTngRutpuN1gSN2UDqTACAxCtdIRHrH5vUaRJqSSL7Phy_1TxYr7_fsjr1V8icezholBZMn1N3r8EQKnvhDcc4pEIww_q4eCf1Dz5RqYMB4gZAlQrBZXysVTlV/s1600/IMG_8885.JPG" /></a><br />
</li>
<li><br />
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgJ3eJve-fho6RieANNsvk1iGA-kqeJTorNXIOl7dfOj-9a3stOOm8NTw4kls3cuyTY_cSgYUZdUIkFTuvFywt-4epwPR_y3T6ZpwrxJxkoJWxaCMbVvCrRRobRNMFg129V3yls/s1600/IMG_8891.JPG" imageanchor="1"><img border="0" data-original-height="1600" data-original-width="1200" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgJ3eJve-fho6RieANNsvk1iGA-kqeJTorNXIOl7dfOj-9a3stOOm8NTw4kls3cuyTY_cSgYUZdUIkFTuvFywt-4epwPR_y3T6ZpwrxJxkoJWxaCMbVvCrRRobRNMFg129V3yls/s1600/IMG_8891.JPG" /></a><br />
</li>
<li><br />
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjJTYpqXDIGd92FxZR2KJtH29fMkaurYrNI1NeooYRsoJATUEGguoDpKpscXmfrY_BTP9G5DW1ABfHBrPvUorL537nCSvBYZDyvD23TRiJTNOK1HV5L2MbUROZC0HFX9HnpZrMd/s1600/IMG_8887.JPG" imageanchor="1"><img border="0" data-original-height="1600" data-original-width="1200" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjJTYpqXDIGd92FxZR2KJtH29fMkaurYrNI1NeooYRsoJATUEGguoDpKpscXmfrY_BTP9G5DW1ABfHBrPvUorL537nCSvBYZDyvD23TRiJTNOK1HV5L2MbUROZC0HFX9HnpZrMd/s1600/IMG_8887.JPG" /></a><br />
</li>
<li><br />
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj7mMGkbXsgXAD34ppbm3ijO7C_Y5JAhpQQxJuQeyngzOnTARFbfNxJ6KXZwPxw4Fcet1u52TE4QdDFhVf-aR5E22KMvVX0inSXDr4-ahUwmATaNlf4Hd5qs3GgQuAOFZ9Ylzvo/s1600/IMG_8888.JPG" imageanchor="1"><img border="0" data-original-height="1600" data-original-width="1200" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj7mMGkbXsgXAD34ppbm3ijO7C_Y5JAhpQQxJuQeyngzOnTARFbfNxJ6KXZwPxw4Fcet1u52TE4QdDFhVf-aR5E22KMvVX0inSXDr4-ahUwmATaNlf4Hd5qs3GgQuAOFZ9Ylzvo/s1600/IMG_8888.JPG" /></a><br />
</li>
<li><br />
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhw03wG1wj7lrVEV7lGCUOazcFkXKJgrahxrLRLoSE_8PprBayyfDM4Jyh9rNv3EWbYNfPWpp1PD8S1gMISYf-xtRjD4KUl9JvlM39h6W-nAqE-vno02ehwLVplKKZ0EC8X8FWW/s1600/IMG_8889.JPG" imageanchor="1"><img border="0" data-original-height="1600" data-original-width="1200" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhw03wG1wj7lrVEV7lGCUOazcFkXKJgrahxrLRLoSE_8PprBayyfDM4Jyh9rNv3EWbYNfPWpp1PD8S1gMISYf-xtRjD4KUl9JvlM39h6W-nAqE-vno02ehwLVplKKZ0EC8X8FWW/s1600/IMG_8889.JPG" /></a><br />
</li>
<li><br />
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg1ttYX4VtybXoXQVwfxeARwpzgznmOFmvz7t63FrB-ILEDajohg_ZKUsPmMDhBbicaro3tg37RA81sVfgm6Y2-cRYt5cLqRfomgRLsCOBYD0HoF7WXu7FLlPRIJlnZKDxFHR_d/s1600/IMG_8892.JPG" imageanchor="1"><img border="0" data-original-height="1600" data-original-width="1200" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg1ttYX4VtybXoXQVwfxeARwpzgznmOFmvz7t63FrB-ILEDajohg_ZKUsPmMDhBbicaro3tg37RA81sVfgm6Y2-cRYt5cLqRfomgRLsCOBYD0HoF7WXu7FLlPRIJlnZKDxFHR_d/s1600/IMG_8892.JPG" /></a><br />
</li>
<li><br />
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg3lGtBTsPyX5kQDXQ4rHfUoJkxX2WiaK7agqdF0vomb6mQdJeZryuRKGs3cZWxos_72giZugrJd7kkiJAxjpf6IEm7MlKtsuiTP_9JgFkmuktjO1h538VRoqWJixgv9SgbVVOB/s1600/sp-action.gif" imageanchor="1"><img border="0" data-original-height="300" data-original-width="224" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg3lGtBTsPyX5kQDXQ4rHfUoJkxX2WiaK7agqdF0vomb6mQdJeZryuRKGs3cZWxos_72giZugrJd7kkiJAxjpf6IEm7MlKtsuiTP_9JgFkmuktjO1h538VRoqWJixgv9SgbVVOB/s1600/sp-action.gif" /></a><br />
</li>
<li><br />
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiUMvh4bc7ZGxu7PYGpAVnEPVhLI0XiNLM5x-k0k_cvNm11amzGnuZzpT02TQ8skVlEYSp3_5IFmfmL7Q-pP09bUon35DZy68MSIPt3jNILTcGmdiaQwzFDdDiIdw2awgcth-No/s1600/sp-motor.gif" imageanchor="1"><img border="0" data-original-height="300" data-original-width="224" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiUMvh4bc7ZGxu7PYGpAVnEPVhLI0XiNLM5x-k0k_cvNm11amzGnuZzpT02TQ8skVlEYSp3_5IFmfmL7Q-pP09bUon35DZy68MSIPt3jNILTcGmdiaQwzFDdDiIdw2awgcth-No/s1600/sp-motor.gif" /></a><br />
</li>
</ul>
</div>
<div>
</div>
<div>
<br />
<br />
That turned out way longer of a blog post than I wanted, but hopefully it's useful. Enjoy! <br />
<br />
<br />
<br /></div>
<div>
</div>
</div>
doschmanhttp://www.blogger.com/profile/00219948412523833756noreply@blogger.com1tag:blogger.com,1999:blog-27141794.post-29191571259054478152016-01-01T22:16:00.001-06:002016-01-03T16:11:51.993-06:00Getting Q-logic 2532/2562 (qla2xxx) and Linux-IO SCSI Target Working On RedHat/CentOS 6.7Having oodles of enterprise shit at work makes me a bit spoiled, so it's nice to have some sliver of that at home. So one of the things I've wanted to do for some time now is have as-real-as-possible-to-me fibre channel SAN to work with at home but do it as minimalistic as possible.<br />
<br />
However, a few things that won't be happening:<br />
<ol>
<li>Not buying and/or firing up any sort of rack-mount entry/mid/enterprise storage array at my place</li>
<li>Making my eletric bill any more hefty from the amount of shit already running in my little datacenter close</li>
<li>Have my wife draft up divorce papers for increasing the amount of space I'm already taking up with my stuff</li>
</ol>
<div>
A few things that are essential requirements (for me) for this:</div>
<div>
<ol>
<li>Reusing whatever hardware I have at my place and not buying anything of significant real expense</li>
<li>Keep a small footprint (e.g. contained a mini-ATX case at most)</li>
<li>Operational and managable on top of a full OS installation of CentOS/RHEL 6.x</li>
</ol>
</div>
So, the compromise to all of this is a cheap, Brocade fibre channel switch and using <a href="http://linux-iscsi.org/wiki/Main_Page" target="new">Linux-IO SCSI</a> target package.<br />
<br />
If you did any sort of high-level googling, you'd see that are successful and documented examples of this here, here and here with newer Linux distro's using Linux Kernel 3.x and Linux-IO 3.x packages.<br />
<br />
<h3>
Reason For Doing This</h3>
<div>
<br />
The reason I am doing this:</div>
<div>
<ul>
<li>Because I need something to do on my 2015 holiday break from work</li>
<li>I stubbornly still run RHEL/CentOS 6.x distros because of my ever loving HATE of 'system-d'</li>
<li>RHEL/CentOS 6.x uses a stable but relic 2.6.x kernel --- which Q-Logic HBA fibre channel target mode is not merged into (obviously)</li>
<li>Even with a support Linux kernel that has Q-Logic HBA fibre channel support (3.x+), the Linux-IO packages for RHEL/CentOS 6.x (fcoe-target-utils) still won't work and you have to re-build those so it picks up the support in configFS under sysfs. Since the tools are written in python, without digging into any code in 'targetcli' or 'rtslib', I'm leaning towards 'rtslib' being the outdated piece of fcoe-target-utils.</li>
<li>I'm sure one could have tracked and gathered a bunch of patches to see if it's possible to merge the tcm_qla2xxx + sysfs changes into the stock CentOS 6.7 (2.6.32-573.el6.x86_64) but it's just easier to re-compile the whole thing.</li>
</ul>
<div>
<h3>
What Else this is useful for</h3>
<div>
<br />
There seems to be a lot of buzz off other people's blog posts about even folks using RHEL/CentOS 7.x not being able to get qla2xxx working. Again, I lean on either parsing in 'targetcli' or 'rtslib' as a complete wild ass guess being the issue, since tcm_qla2xxx module is already pre-compiled and availbale with the stock kernels.<br />
<br />
My advice would be just skip down to the latest-and-greatest Linux-IO compilation builds to get yourself going.<br />
<br /></div>
</div>
</div>
<h3>
Install Needed Packages</h3>
<div>
<br /></div>
<div>
<br />
Depending on how you baseline your RHEL/CentoOS 6.x installs, you'll definitely want to install these packages via 'yum' (and possibly more). I'll order these by the groups of things you'll need the packages for just so it makes sense as far as what is depended for what.</div>
<div>
<br /></div>
<div>
For Linux kernel compiling:</div>
<div>
<br /></div>
<div>
<pre class="prettyprint" style="font-size: 10px;">$ yum install gcc ncurses-devel kernel-devel lsscsi patch git -y
</pre>
</div>
<div>
<br /></div>
<div>
For Linux-IO configshell, rtslib and targetcli latest rebuild:</div>
<div>
<br /></div>
<div>
<pre class="prettyprint" style="font-size: 10px;">$ yum install python-devel epydoc python-pyparsing python-configobj python-prettytable -y
</pre>
</div>
<div>
<br /></div>
<div>
Extra RPMs you will have to hand-install and can easily find on rpm.pbone.net for Linux-IO rebuild:</div>
<div>
<ul>
<li><a href="ftp://ftp.pbone.net/mirror/dag.wieers.com/redhat/el6/en/i386/dag/RPMS/python-pyparsing-1.5.6-2.el6.rf.noarch.rpm" target="_blank">python-pyparsing</a></li>
<li><a href="ftp://ftp.pbone.net/mirror/ftp5.gwdg.de/pub/opensuse/repositories/home:/aevseev/CentOS_CentOS-6/x86_64/python-netifaces-0.8-3.1.x86_64.rpm" target="_blank">python-netifaces</a></li>
</ul>
<div>
<br /></div>
</div>
<h3>
Build Linux 3.x Kernel (3.18.25)</h3>
<div>
<br />
This is a pretty clean-cut set of step(s) to get the kernel rebuilt and do the bare minimum tweak of enabling the build of the Q-logic TCM_QLA2XXX fabric module for Qlogic 2xxx series target mode HBAs:<br />
<h3>
<br />
</h3>
<h2>
Download and Unpack Linux Kernel Source</h2>
<br />
First step is to download and unpack the Linux kernel source:<br />
<br />
<pre class="prettyprint" style="font-size: 10px;">$ wget --no-check-certificate https://cdn.kernel.org/pub/linux/kernel/v3.x/linux-3.18.25.tar.xz
$ tar zxvf linux-3.18.25.tar.xz</pre>
<h3>
<br />
</h3>
<h2>
Copy Existing Kernel Configuration and Configure Kernel Build</h2>
<br />
Next is to copy over our latest stock kernel configuration for our CentOS as a starting configuration point so, if you want, you can build at a minimum what you have configured in your big, bloated distro kernel plus whatever you are going to enable. Do note, there are numerous changes between 2.6 and any 3.x or 4.x kernel, so again, I'm not advocating this, but for the sake of 'getting shit done via blog directions', it'll do. <br />
<br />
Let's change directory into the kernel source and run our ncurses text-based kernel configuration menu:<br />
<br />
<pre class="prettyprint" style="font-size: 10px;">$ \cp /boot/config-2.6.32-573.el6.x86_64 /path/to/linux-3.18.25/.config
$ cd linux-3.18.25
$ make menuconfig
</pre>
<br />
You'll want to, at a minimum, navigate to the following menu tree to enable Q-logic TCM_QLA2XXX fabric module for Qlogic 2xxx series target mode HBAs:<br />
<br />
<pre class="prettyprint" style="font-size: 10px;">Location:
-> Device Drivers
-> SCSI device support
-> SCSI low-level drivers (SCSI_LOWLEVEL [=y])
-> QLogic QLA2XXX Fibre Channel Support (SCSI_QLA_FC [=m])
-> [m] TCM_QLA2XXX fabric module for Qlogic 2xxx series target mode HBAs
</pre>
<br />
You can toggle on module (e.g. m) build by using your space-bar. Then exit out of the menu's and save the configuration. <br />
<br />
If you're super leery if you did the right thing or not, run this:<br />
<br />
<pre class="prettyprint" style="font-size: 10px;">$ cat linux-3.18.25/.config | grep -q "CONFIG_TCM_QLA2XXX=m" && echo "enabled" || echo "not enabled"
enabled
$
</pre>
<br />
...if you see 'not enabled' echo'd on the screen, you didn't get it enabled. So you can either hand-edit that configuration line into '.config' or go back through ncurses menuconfig and re-enable it. Either or will work.<br />
<br />
Once your configuration is saved, we can build the linux kernel.<br />
<h3>
<br />
</h3>
<h2>
Build the Kernel and Modules</h2>
</div>
<div>
<br />
To build the kernel and it's accompanied modules, simply type:</div>
<div>
<br /></div>
<div>
<pre class="prettyprint" style="font-size: 10px;">$ make -j4 bzImage modules
</pre>
</div>
<div>
<br /></div>
<div>
...then go get some coffee. If you compile with all the CentOS configured extra modules and add-in's you had with your stock os kernel, you're looking at just under one hour for a multi-threading build above.<br />
<br />
Also, you'll definitely want to adjust '-j <n>' to your tastes; this runs automake with <n> threads. Try to, at a minimum, make <n> equal to the number of cores you have on your system you are building on.</div>
<div>
<h2>
<br />
</h2>
<h3>
Install and Boot Into 3.x Kernel</h3>
</div>
<div>
<br />
After your kernel and modules build (successfully, I hope), it's time to install the kernel and the modules onto your system. The linux kernel build strap scripts have come a LONG ways over the years and they work pretty flawelessly.<br />
<br />
<br /></div>
<h2>
Add 'qla2xxx' target mode parameter for kernel module</h2>
<div>
This is an important step so prior to using the kernel build strap scripts for installing the kernel modules and invoking 'dracut', will automagically grab these options and incorporate them into your ramdisk (e.g. initrd).</div>
<div>
<br /></div>
<div>
Run the following command(s) to add the target mode enable options for the qla2xx fibre channel module:</div>
<div>
<br /></div>
<div>
<pre class="prettyprint" style="font-size: 10px;">$ echo "options qla2xxx qlini_mode=\"disabled\"" >> /etc/modprobe.d/qla2xxx.conf</pre>
</div>
<h2>
<br />
</h2>
<h2>
Install Kernel, Modules and config</h2>
<div>
<br />
To install the kernel modules, do the following:</div>
<div>
<br /></div>
<div>
<pre class="prettyprint" style="font-size: 10px;">$ make modules_install
</pre>
</div>
<div>
<br /></div>
<div>
To install the kernel, do the following:</div>
<div>
<br /></div>
<div>
<pre class="prettyprint" style="font-size: 10px;">$ make install
</pre>
</div>
<div>
<br /></div>
<div>
This isn't a necessary step, but for the sake of making our custom kernel 'look and feel' the same, let's copy over the configuration as well to the /boot directory:</div>
<div>
<br /></div>
<div>
<pre class="prettyprint" style="font-size: 10px;">$ cp linux-3.18.25/.config /boot/config-3.18.25
</pre>
</div>
<div>
<br /></div>
<div>
Double-check the GRUB2 entries in '/etc/grub.conf' as well. If you're super paranoid, you may also want to look at the contents of your in ramdisk (e.g. initrd) to make sure you got the 'qla2xxx' and 'tcm_qla2xxx' modules in there.</div>
<h2>
<br />
</h2>
<h2>
Reboot into New Kernel</h2>
<div>
Let's reboot your system:</div>
<div>
<br /></div>
<div>
<pre class="prettyprint" style="font-size: 10px;">$ init 6
</pre>
</div>
<div>
<br /></div>
<div>
We are going to assume you're going to leave your existing, distro-built kernel as 'default' and you'll manually select the 3.18.25 kernel from your GRUB menu.</div>
<div>
<br /></div>
<div>
If you don't and want to boot into this from the get-go without any intervention (e.g. maybe you're running a headless box like I am OR you're cocky as shit), just edit '/etc/grub.conf' and change the following line back to:</div>
<div>
<br /></div>
<div>
<pre class="prettyprint" style="font-size: 10px;">default=0
</pre>
</div>
<div>
<br /></div>
<div>
...so the bootloader defaults to the first-most kernel entry, which the linux kernel build strap scripts will put your new kernel at the top of the available kernels-to-boot list.</div>
<div>
<br /></div>
<div>
Do whatever you want to do.</div>
<div>
<br /></div>
<div>
<h2>
Verify Kernel Installation</h2>
</div>
<div>
To do a quick kernel installation verification, obviously having the system back and booted is a probably the top indicator.</div>
<div>
<br /></div>
<div>
Next, let's verify the kernel we are booted into is, in fact, the one we built (sounds funny, but I have shot myself in the foot MANY times by overlooking that and skipping a few steps doing this by-the-cuff):</div>
<div>
<br /></div>
<div>
<pre class="prettyprint" style="font-size: 10px;">$ uname -r
3.18.25
$
</pre>
</div>
<br />
<div>
Next, lets verify that our Q-logic module(s) can be loaded (assuming the card isn't plugged into any SAN fabric or have any existing storage attached/zoned to it). You should see similar when running 'dmesg':<br />
<br /></div>
<div>
<pre class="prettyprint" style="font-size: 10px;">$ dmesg | grep -i qla
qla2xxx [0000:00:00.0]-0005: : QLogic Fibre Channel HBA Driver: 8.07.00.16-k.
qla2xxx [0000:02:00.0]-001d: : Found an ISP2532 irq 16 iobase 0xffffc90004afe000.
qla2xxx 0000:02:00.0: irq 26 for MSI/MSI-X
qla2xxx 0000:02:00.0: irq 27 for MSI/MSI-X
scsi host10: qla2xxx
qla2xxx [0000:02:00.0]-00fb:10: QLogic QLE2560 - PCI-Express Single Channel 8Gb Fibre Channel HBA.
qla2xxx [0000:02:00.0]-00fc:10: ISP2532: PCIe (5.0GT/s x8) @ 0000:02:00.0 hdma+ host#=10 fw=7.03.00 (90d5).
$</pre>
<div>
<div>
<br />
Lastly, lets load the target SCSI module we added and make sure that loads:<br />
<br />
<pre class="prettyprint" style="font-size: 10px;">$ modprobe tcm_qla2xxx</pre>
</div>
<div>
<br />
<h3>
Build the Latest Linux-IO Packages</h3>
<br />
Below are to-the-points steps to rebuild the latest and greatest Linux-IO packages you'll need since even after having the new kernel that supports Q-logic 256x target support, the current relic 'targetcli' package set still won't work.<br />
<br />
<h2>
Make sure 'fcoe-target-utils is Uninstalled</h2>
<br />
Before we go any further, let's make sure anything related to the stock distro 'fcoe-target-utils' is uninstalled and NOT on our system:<br />
<br />
<div>
<pre class="prettyprint" style="font-size: 10px;">$ yum remove fcoe-target-utils python-rtslib python-configshell -y
</pre>
</div>
<br />
<h2>
Build and Install Configshell</h2>
<br />
To build and install the latest/greatest configshell, do the following command(s):<br />
<br />
<div>
<pre class="prettyprint" style="font-size: 10px;">$ git clone https://github.com/Datera/configshell.git
$ cd configshell
$ make rpm
$ cd dist
$ rpm -ivh python-configshell-1.6.1~g020d540-1.el6.noarch.rpm
</pre>
</div>
<br />
<h2>
Build and Install RTSLib</h2>
<br />
To build and install the latest/greatest RTSLib, do the following command(s):<br />
<br />
<div>
<pre class="prettyprint" style="font-size: 10px;">$ git clone https://github.com/Datera/rtslib.git
$ cd configshell
$ make rpm
$ cd dist
$ rpm -ivh python-rtslib-3.0.pre4.9~g6fd0bbf-1.el6.noarch.rpm
</pre>
</div>
<br />
<h2>
Build and Install TargetCLI</h2>
<br />
To build and install the latest/greatest TargetCLI, do the following command(s):<br />
<br />
<div>
<pre class="prettyprint" style="font-size: 10px;">$ git clone https://github.com/Datera/targetcli.git
$ cd configshell
$ make rpm
$ cd dist
$ rpm -ivh targetcli-3.0.pre4.5~ga125182-1.el6.noarch.rpm
</pre>
</div>
<br />
<div>
<h2>
Verify 'targetcli' is working</h2>
</div>
<br />
Lastly, a simple verification and what will look different from using the 'fcoe-target-util' package targetcli command is the actual qla2xxx target config being loaded so you can set up your block storage backstores for export. You'll also notice in the output of targetcli it references the rtslib build version we just build and installed via RPM, too:<br />
<br />
<div>
<pre class="prettyprint" style="font-size: 10px;">$ targetcli
targetcli 3.0.pre4.5~ga125182 (rtslib 3.0.pre4.9~g6fd0bbf)
Copyright (c) 2011-2014 by Datera, Inc.
All rights reserved.
/> qla2xxx/ info
Fabric module name: qla2xxx
ConfigFS path: /sys/kernel/config/target/qla2xxx
Allowed WWNs list (free type): 21:00:00:24:xx:xx:xx:xx
Fabric module specfile: /var/target/fabric/qla2xxx.spec
Fabric module features: acls
Corresponding kernel module: tcm_qla2xxx
/> ls
o- / ............................................................................................................. [...]
o- backstores .................................................................................................. [...]
| o- fileio ....................................................................................... [0 Storage Object]
| o- iblock ....................................................................................... [0 Storage Object]
| o- pscsi ........................................................................................ [0 Storage Object]
| o- rd_mcp ....................................................................................... [0 Storage Object]
o- loopback .............................................................................................. [0 Targets]
o- qla2xxx ............................................................................................... [0 Targets]
/>
</pre>
</div>
<div>
That's it (in a big nutshell)! You should now be able to continue on setting up your block storage to front as a backstore from your newly set up fibre channel target.</div>
</div>
</div>
</div>
doschmanhttp://www.blogger.com/profile/00219948412523833756noreply@blogger.com2tag:blogger.com,1999:blog-27141794.post-86418568968327253672015-08-31T08:54:00.000-05:002015-08-31T10:40:42.907-05:00Adding 'Hack' monospace font functionality into Spyder IDE in Fedora Core 21As of late, a lot of the code I have been hacking out for just about anything has been straight, 100% Python. With that, I've also ditched 'vi' + plugins and have grown extremely comfortable (and probably complacent?) using <a href="https://github.com/spyder-ide/spyder" target="_blank">Spyder IDE</a> GUI. I never wanted to be GUI dependent (again) but I am, so whatever. I deal with it.<br />
<br />
But, recently, I saw a post on <a href="http://arstechnica.com/information-technology/2015/08/open-source-typeface-hack-brings-design-to-source-code/" target="_blank">arstechnica.com</a> touting the coolness of <a href="http://sourcefoundry.org/hack/" target="_blank">Hack</a>, an open-source monospace font marketed towards the code slingers of the world. <br />
<br />
I undoubtedly get tired of using of the defacto DejaVu and Liberation monospace fonts and decided to give this a shot. And quite honestly, even though it's subtle, I really like it.<br />
<br />
<b>Characters of note: </b> I don't notice the lowercase-L vs. the numeral 1 as much as I do the zero vs. uppercase-O and lowercase-I curvature.<br />
<br />
<b>Font sizes:</b> I think my favorite font size is 9px or 11px (11px especially if I've been staring at my monitor for more than 4 hour straight with contacts in to boot!)<br />
<br />
The overall font character scheme also seems a bit more compressed as well, which is nice so I 'feel' like I'm getting more width real-estate. Case in point: take it for what it's worth. <br />
<br />
Even though this is a less traditional and definitely 'non-distro' way to add an overall font to your OS, I think it gives most people the flexibility enough to give it a shot themselves with as minimal overhead as possible, especially if you want it 'long-term' and want to put it in the same place as your other distro fonts via package management without creating a distro package for it.<br />
<br />
Here's how to make the 'Hack' monospace font accessible in Spyder IDE under Fedora (or any other RHEL based OS for that matter).<br />
<br />
If you really want to get technical and overview-ish, I guess this would be a good way to hack-and-slash 'any' font you want to Spyder, monospace or not.<br />
<br />
<b><span style="font-size: large;">Download and Unzip 'Hack' Font from SourceFoundary</span></b><br />
<br />
Go to Hack's SourceFoundary site and <a href="http://sourcefoundry.org/hack/#download" target="_blank">download</a> the True-Type font .zip archive. <br />
<br />
Once you have downloaded the 'Hack' fonts, simply <span style="font-family: Courier New, Courier, monospace;">unzip</span> them wherever you want:<br />
<br />
<pre class="prettyprint" style="font-size: 10px;">$ cd /path/to/hack/fonts/
$ unzip Hack-v2_010-ttf.zip
unzip Hack-v2_010-ttf.zip
Archive: Hack-v2_010-ttf.zip
inflating: Hack-Bold.ttf
inflating: Hack-BoldOblique.ttf
inflating: Hack-Regular.ttf
inflating: Hack-RegularOblique.ttf
$
</pre>
<br />
<b><span style="font-size: large;">Add 'Hack' font into to your OS</span></b><br />
<br />
Adding the Hack monospace font (this way) is pretty trivial. The key point here is to know the top-level path where your Linux distro stashes it's fonts. For a font like this that I really want to use long-term, I think this is a better solution than putting it in <span style="font-family: Courier New, Courier, monospace;">~/.fonts/</span> or equivalent. I'm also going to assume you have proper privileges to do all these command(s) or know how to obtain it (e.g. NOT prefacing the sudo command to obvious root-level stuff)<br />
<ul>
<li>Create a new directory for the 'Hack' font in your Linux distro's top-level system font path</li>
<pre class="prettyprint" style="font-size: 10px;">$ mkdir /usr/share/fonts/hack
</pre>
<li>Copy fonts over</li>
<pre class="prettyprint" style="font-size: 10px;">$ cp -a /path/to/hack/fonts/Hack-*.ttf /usr/share/fonts/hack/
</pre>
<li>Make sure permissions + ownership are sane on your font directory and fonts</li>
<pre class="prettyprint" style="font-size: 10px;">$ chown -R root:root /usr/share/fonts/hack && chmod 755 /usr/share/fonts/hack</pre>
</ul>
<b><span style="font-size: large;">Changes to Spyder IDE</span></b><br />
<br />
I'm using Spyder IDE v2.2.4, so YMMV if you're using another version. I didn't go scout all this out, but it's pretty self-explanatory. <br />
<br />
Spyder IDE has a default, hard-coded list of approve and available monospace fonts that are defacto standards. All you have to do is alter the list data structure defining the list of monospace fonts in spyderlib. <br />
<br />
To do this, you'll want to look for the following line of code in <span style="font-family: Courier New, Courier, monospace;">/usr/lib/python2.7/site-packages/spyderlib/config.py</span> module:<br />
<br />
<pre class="prettyprint" style="font-size: 10px;">MONOSPACE = ['Monospace', 'DejaVu Sans Mono', 'Consolas', 'Monaco',
'Bitstream Vera Sans Mono', 'Andale Mono', 'Liberation Mono',
'Courier New', 'Courier', 'monospace', 'Fixed', 'Terminal']
</pre>
<br />
...and add in the 'Hack' fonts into the MONOSPACE list structure so it looks something like this:<br />
<br />
<pre class="prettyprint" style="font-size: 10px;">MONOSPACE = ['Monospace', 'DejaVu Sans Mono', 'Consolas', 'Monaco',
'Bitstream Vera Sans Mono', 'Andale Mono', 'Liberation Mono',
'Courier New', 'Courier', 'monospace', 'Fixed', 'Terminal',
'Hack-Regular', 'Hack-RegularOblique.ttf', 'Hack-Bold.ttf',
'Hack-BoldOblique.ttf']
</pre>
<br />
<b>NOTE: </b> There are several 'config.py' modules in Spyder IDE, so if you're really confused at this point, just do a case-insensitive recursive grep (e.g. <span style="font-family: Courier New, Courier, monospace;">grep -i -R "MONOSPACE" /path/to/spyderide/site-package/install</span>) and find the right one to edit.<br />
<br />
<b><span style="font-size: large;">Restart Spyder IDE and Choose 'Hack' as your Font</span></b><br />
<br />
If you still have Spyder IDE running, close it and re-open it. <br />
<br />
Then on Sypder's top menu bar, you'll want to navigate to 'Tools > Preferences', then select the 'Editor' option on the left-hand side. Now, if you select the 'font' drop-down menu, you should see 'Hack' available for your choosing:<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhgZJndXNMdsMLqr4RPdwgOEKHYY37xka0inNSSZ-MgLbwDmRRadsLV8ox4baPVzYrXHOT2vrgMkJezPzDZt4qcVkVAv2kbAU5EoMQZsoqFAFcb8SyWIkA3-F_LRfOLQ7wcnVCp/s1600/hack_spyder.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="188" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhgZJndXNMdsMLqr4RPdwgOEKHYY37xka0inNSSZ-MgLbwDmRRadsLV8ox4baPVzYrXHOT2vrgMkJezPzDZt4qcVkVAv2kbAU5EoMQZsoqFAFcb8SyWIkA3-F_LRfOLQ7wcnVCp/s320/hack_spyder.png" width="320" /></a></div>
<br />
<br />
You can now click 'Apply' and watch all those wonderful tabs of 'code' change over to using 'Hack'.<br />
<br />
If you also want your Python console in Spyder to use this font as well, just select 'Console' and change it there, too. <br />
<br />
<b><span style="font-size: large;">Before-and-After of Hack vs. DejaVu Sans</span></b><br />
<br />
Here's a couple of quick screenshots put in extra-large to show the differences of Hack vs. DejaVu Sans out-of-the-box Spyder IDE font:<br />
<br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi3I4cC9KyByz4CYpa_O7Xx00dkwHlmuSjHbSd6ujLYBJ1k_YFWXo56pfbirx2m1fYVkUdkXQOoG-TBankzc7gOTD9IW2ZaV4FoajmYY5q4l7JsIBT-pqx4dlkJLI9yX-CkVUJN/s1600/dejavu_screener.png" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" height="263" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi3I4cC9KyByz4CYpa_O7Xx00dkwHlmuSjHbSd6ujLYBJ1k_YFWXo56pfbirx2m1fYVkUdkXQOoG-TBankzc7gOTD9IW2ZaV4FoajmYY5q4l7JsIBT-pqx4dlkJLI9yX-CkVUJN/s400/dejavu_screener.png" width="400" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;"><b>DejaVu Sans - Normal - 9px</b></td></tr>
</tbody></table>
<br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh_xGbfneaZgi2xlz4VjQQTp-9Pxk5TCuz3MYb0n_m3TskI5tOyu6yZqXjrfpAp8wwPbhgVzevVUK1GMnB2snL0c6vzuGpE-33q6KMSFCBeo8hVx1oGiv_wh5Fv6B8H5PyBYUln/s1600/hack_screener.png" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" height="275" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh_xGbfneaZgi2xlz4VjQQTp-9Pxk5TCuz3MYb0n_m3TskI5tOyu6yZqXjrfpAp8wwPbhgVzevVUK1GMnB2snL0c6vzuGpE-33q6KMSFCBeo8hVx1oGiv_wh5Fv6B8H5PyBYUln/s400/hack_screener.png" width="400" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;"><b>Hack - Normal - 9px</b></td></tr>
</tbody></table>
<br />
<br />
Now as much as I'd want to package this into an RPM for my own sake in case some update comes about, that would just be more work than it's worth.<br />
<br />
Enjoy!doschmanhttp://www.blogger.com/profile/00219948412523833756noreply@blogger.com3tag:blogger.com,1999:blog-27141794.post-8919303650106720492013-01-20T01:43:00.005-06:002015-08-31T10:46:43.228-05:001PPS Support with GPIO For Raspberry Pi in Fedora 17 Remix<span style="font-family: Verdana, sans-serif;">One of my projects as of the last 5 months (although slow going) is making a full-out stratum-1 time server appliance out of the Raspberry Pi. I'm going to be using an EM408 GPS module + generating my own 1PPS signal with an AVR attiny84 microcontroller inputting into GPIO on the Pi, and if i have enough GPIO left, will be driving a 16x4 LCD parallel output-only display for fun as well.</span><br />
<div><div><span style="font-family: Verdana, sans-serif;"><br />
</span></div><div><span style="font-family: Verdana, sans-serif;">When it comes to just using the Raspberry Pi as a NTP stratum-1 server, there's quite a few documented artifacts out there on the <i>internets</i> already being done, most notably from David Taylor's excellent <a href="http://www.satsignal.eu/ntp/Raspberry-Pi-NTP.html" target="_blank">documentation</a> on his website. </span></div><div><span style="font-family: Verdana, sans-serif;"><br />
</span></div><div><span style="font-family: Verdana, sans-serif;">It's worthy to note that most, if not all, Raspberry Pi Linux distribution spins DO NOT come with </span><span style="font-family: Courier New, Courier, monospace;">CONFIG_PPS</span><span style="font-family: Verdana, sans-serif;"> or </span><span style="font-family: Courier New, Courier, monospace;">CONFIG_PPS_CLIENT_GPIO</span><span style="font-family: Verdana, sans-serif;"> compiled into the kernel or as modules. </span></div><div><span style="font-family: Verdana, sans-serif;"><br />
</span></div><div><span style="font-family: Verdana, sans-serif;">I'm not totally down with the amount of hackery floating around to insert dirty modules into the kernel. Ya, it works. Yes, if you have </span><span style="font-family: Courier New, Courier, monospace;">CONFIG_MODVERSIONS</span><span style="font-family: Verdana, sans-serif;"> set, then you should be able to install modules not compiled with your kernel into it. However, I'm rolling with Fedora 17 remix and option isn't compiled in with the stock kernel. So either way, I had to result to building my own RPMs for this. </span></div><div><span style="font-family: Verdana, sans-serif;"><br />
</span></div><div><span style="font-family: Verdana, sans-serif;">If you're interested in getting 1PPS supprt on the Raspberry Pi via GPIO (like I and many other time enthusiasts are), then here's some steps to get you in the right direction. </span><span style="font-family: Verdana, sans-serif;">Below are some options you have:</span></div><h3><span style="font-family: Verdana, sans-serif;"><br />
</span></h3><h3><span style="font-family: Verdana, sans-serif;">Download 1PPS Packaged RPM for Fedora 17 Remix</span></h3><div><span style="font-family: Verdana, sans-serif;"><br />
</span> <span style="font-family: Verdana, sans-serif;">Here's a link to my binary RPM package for 1PPS, which includes support for:</span></div><div><ul><li><span style="font-family: Verdana, sans-serif;">PPS Support (</span><span style="font-family: Courier New, Courier, monospace;">CONFIG_PPS=m</span><span style="font-family: Verdana, sans-serif;">)</span></li>
<li><span style="font-family: Verdana, sans-serif;">PPS Source using GPIO pin (</span><span style="font-family: Courier New, Courier, monospace;">CONFIG_PPS_CLIENT_GPIO=m</span><span style="font-family: Verdana, sans-serif;">)</span></li>
</ul></div><div>Download from: <a href="http://www.wisehippy.com/files/">http://www.wisehippy.com/files/</a></div><div><br />
</div><div>NOTE: Yes, I am using the FC 18 source rpm, but they will install on FC 17. I have tested.</div><h3><span style="font-family: Verdana, sans-serif;"><br />
</span></h3><h3><span style="font-family: Verdana, sans-serif;">Build your own Kernel + RPMs</span></h3></div><div><span style="font-family: Verdana, sans-serif;"><br />
</span> <span style="font-family: Verdana, sans-serif;">There's quite a few step(s) I'll omit since it's clearly beyond the scope of this blog post, but here's a quick and dirty run-down on how to do it on an RPM-based Linux distribution:</span></div><div><span style="font-family: Verdana, sans-serif;"><br />
</span></div><div><span style="font-family: Verdana, sans-serif;">1) Build yourself a soft-float ARM cross compiler (at least for Fedora 17 remix) using </span><a href="https://www.google.com/url?sa=t&rct=j&q=&esrc=s&source=web&cd=1&cad=rja&ved=0CDUQFjAA&url=http%3A%2F%2Fcrosstool-ng.org%2F&ei=iZr7UODdGcTQ2QXEsID4BA&usg=AFQjCNECVETJfSr0TKD-JTfCrtsP-an2Gw&bvm=bv.41248874,d.b2U" style="font-family: Verdana, sans-serif;">crosstool-ng</a></div><div><span style="font-family: Verdana, sans-serif;"><br />
</span></div><div><span style="font-family: Verdana, sans-serif;">2) Set up your RPM build environment using `rpmdev-setuptree`</span></div><div><span style="font-family: Verdana, sans-serif;"><br />
</span></div><div><span style="font-family: Verdana, sans-serif;">3) Download the raspberry-pi-kernel source RPM from</span><span style="font-family: Verdana, sans-serif;"> </span><a href="http://scotland.proximity.on.ca/raspberrypi/raspberrypi-fedora-remix/17/packages/source/" style="font-family: Verdana, sans-serif;">here</a></div><div><span style="font-family: Verdana, sans-serif;"><br />
</span></div><div><span style="font-family: Verdana, sans-serif;">4) Patch the kernel config ( in SOURCES folder) and .spec file (in SPECS folder) using `patch` with my patches that are posted on the Fedora Remix as an 'enhancement' option: </span><a href="https://fedorahosted.org/arm/ticket/64">https://fedorahosted.org/arm/ticket/64</a></div><div><span style="font-family: Verdana, sans-serif;"><br />
</span></div><div><span style="font-family: Verdana, sans-serif;">5) Rebuild kernel package + sub-packages with: </span></div><div><span style="font-family: Verdana, sans-serif;"><br />
</span></div><div><pre class="prettyprint" style="font-size: 10px"># rpmbuild -bb --clean --target=armv5tel raspberrypi-kernel.spec
</pre></div><div><span style="font-family: Verdana, sans-serif;"><br />
</span></div><div><span style="font-family: Verdana, sans-serif;">6) Copy 'at least' the kernel-pps RPM package to you RPi and install with:</span></div><div><span style="font-family: Verdana, sans-serif;"><br />
</span></div><div><pre class="prettyprint" style="font-size: 10px"># rpm -ivh raspberrypi-kernel-pps-3.2.27-1.20120926git9245b4c.rpfr18.armv5tel.rpm
</pre></div><div><span style="font-family: Verdana, sans-serif;"><br />
</span></div><div><span style="font-family: Verdana, sans-serif;">7) On the RPi, run:</span></div><div><span style="font-family: Verdana, sans-serif;"><br />
</span></div><div><pre class="prettyprint" style="font-size: 10px"># modprobe pps-gpio
</pre></div><div><span style="font-family: Verdana, sans-serif;"><br />
</span></div><div><span style="font-family: Verdana, sans-serif;"> ...then verify the module loaded correctly with:</span></div><div><span style="font-family: Verdana, sans-serif;"><br />
</span></div><div><pre class="prettyprint" style="font-size: 10px"># dmesg
</pre><span style="font-family: Verdana, sans-serif;"><br />
</span> <span style="font-family: Verdana, sans-serif;"> ...and look for some output like:</span><br />
<pre class="prettyprint" style="font-size: 10px">[ 1404.141098] pps_core: LinuxPPS API ver. 1 registered
[ 1404.141123] pps_core: Software ver. 5.3.6 - Copyright 2005-2007 Rodolfo Giometti <giometti linux.it="linux.it">
</giometti></pre></div><div><span style="font-family: Verdana, sans-serif;"><br />
</span></div><div><span style="font-family: Verdana, sans-serif;">Do note that applying my patches in step #4 will also apply some of my other .spec file changes that change the way the kernel image is built and installed on the FC remix distro. Do take a look at the changes and don't apply blindly if you can help it. This only matters if you plan to install my kernel RPM.</span></div><div><span style="font-family: Verdana, sans-serif;"><br />
</span></div><div><span style="font-family: Verdana, sans-serif;">Enjoy!</span></div>doschmanhttp://www.blogger.com/profile/00219948412523833756noreply@blogger.com0tag:blogger.com,1999:blog-27141794.post-54513047782065820872013-01-05T20:21:00.001-06:002015-08-31T10:51:42.730-05:00Calculating NMEA sentence checksums with Python<span style="font-family: Verdana, sans-serif; font-size: x-small;"><br />
</span> <span style="font-family: Verdana, sans-serif;">Another feature I wanted to add to my NTP/GPS project I'm doing with my Raspberry Pi is to validate the NMEA sentences I'm reading in by checksum'ing the NMEA sentence and comparing it with the XOR checksum provided from the GPS receiver.</span><br />
<span style="font-family: Verdana, sans-serif;"><br />
</span> <span style="font-family: Verdana, sans-serif;">This is especially important if you plan on writing an application that is reading $GPGGA, $GPGLL or $GPRMC sentences for timekeeping purposes and want to validate the sentence you read for time is legit or not.</span><br />
<span style="font-family: Verdana, sans-serif;"><br />
</span> <br />
<h3>Background on NMEA Checksums</h3><span style="font-family: Verdana, sans-serif;"><br />
</span> <span style="font-family: Verdana, sans-serif;">After reading some <a href="http://www.gpsinformation.org/dale/nmea.htm">documentation</a> on NMEA sentence types and, more importantly, about checksums, the process is actually quite easy and can be coded up fairly easily.</span><br />
<span style="font-family: Verdana, sans-serif;"><br />
</span> <span style="font-family: Verdana, sans-serif;">Here's the main blurb from the NMEA documentation about the checksum and how to calculate it:</span><br />
<blockquote><i><span style="font-family: Verdana, sans-serif;">Programs that read the data should only use the commas to determine the field boundaries and not depend on column positions. There is a provision for a checksum at the end of each sentence which may or may not be checked by the unit that reads the data. The checksum field consists of a '*' and two hex digits representing an 8 bit exclusive OR of all characters between, but not including, the '$' and '*'. A checksum is required on some sentences.</span></i></blockquote><span style="font-family: Verdana, sans-serif;">Not so hard, right? We need to exclusive OR (XOR) all of the characters (INCLUDING the commas) between the '$' and the '*'. </span><br />
<span style="font-family: Verdana, sans-serif;"><br />
</span> <span style="font-family: Verdana, sans-serif;">Let's do it!</span><br />
<span style="font-family: Verdana, sans-serif;"><br />
</span> <br />
<h3>NMEA Sentence Breakdown</h3><div><br />
</div><span style="font-family: Verdana, sans-serif;">Here's a NMEA sentence example that I will use to show the XOR process on:</span><br />
<br />
<center><span style="font-family: Verdana, sans-serif;">$<span style="color: lime;">GPGGA,174134.000,4345.9112,N,09643.8029,W,1,05,2.7,452.6,M,-27.1,M,,0000</span>*<span style="color: blue;">60</span><br />
</span></center><span style="font-family: Verdana, sans-serif;"><br />
</span> <span style="font-family: Verdana, sans-serif;">The color breakdown is:</span><br />
<span style="font-family: Verdana, sans-serif;"><br />
</span> <span style="font-family: Verdana, sans-serif;"> <b>Black:</b> Two positional characters in the NMEA sentence we need to read our characters </span><br />
<span style="font-family: Verdana, sans-serif;"> from between</span><br />
<span style="font-family: Verdana, sans-serif;"> </span><br />
<span style="font-family: Verdana, sans-serif;"> <b style="background-color: white;"><span style="color: lime;">Green:</span></b> Characters we need to XOR</span><br />
<span style="font-family: Verdana, sans-serif;"> <span style="color: blue;"><b>Blue:</b></span> The calculated checksum we need to compare our calculated checksum against</span><br />
<span style="font-family: Verdana, sans-serif;"><br />
</span> <br />
<h3>Bitwise XOR on NMEA Sentences</h3><div><br />
</div><span style="font-family: Verdana, sans-serif;">As the documentation states, we need to exclusive OR (XOR) all of the characters (INCLUDING the commas) between the '$' and the '*'. </span><br />
<span style="font-family: Verdana, sans-serif;"><br />
</span> <span style="font-family: Verdana, sans-serif;">The process is quite simple: We want to take each character and XOR it with the previous </span><span style="font-family: Arial, Helvetica, sans-serif;">XOR'd output from the last character. The very last character that is XOR'd will be the final checksum value that you'd then compare with the checksum value.</span><br />
<span style="font-family: Arial, Helvetica, sans-serif;"><br />
</span> <span style="font-family: Arial, Helvetica, sans-serif;">If you're a bit fuzzy on on XOR, the bitwise operator in most programming languages is ' ^ ' and the rules are as follows:</span><br />
<span style="font-family: Arial, Helvetica, sans-serif;"><br />
</span> <br />
<ul><li><span style="font-family: Arial, Helvetica, sans-serif;">1 ^ 1 = 0</span></li>
<li><span style="font-family: Arial, Helvetica, sans-serif;">1 ^ 0 = 1</span></li>
<li><span style="font-family: Arial, Helvetica, sans-serif;">0 ^ 1 = 1</span></li>
<li><span style="font-family: Arial, Helvetica, sans-serif;">0 ^ 0 = 0</span></li>
</ul><br />
<div><span style="font-family: Verdana, sans-serif;"><span style="line-height: 19.200000762939453px;">One thing to note, when you start of XOR'ing, you'll want to compare your first character with zero (e.g. 0, 0xFF, 0b0, etc.) so on the next character iteration (which would be the 2nd character in the NMEA string) will XOR against the binary value of the first character. Why is this so? If you look at the XOR rules above, we only need one bit 'on' (or '1') on to bit-flip-it and keep it 'on' (or '1'). So if we XOR against '0', we get our original value back.</span></span></div><div><span style="font-family: Verdana, sans-serif;"><span style="line-height: 19.200000762939453px;"><br />
</span></span></div><div><span style="line-height: 19.200000762939453px;"><span style="font-family: Verdana, sans-serif;">Let's use our example sentence above to go through a handful of binary XOR iterations of what we'll be accomplishing in code:</span></span><br />
<span style="line-height: 19.200000762939453px;"><span style="font-family: Verdana, sans-serif;"><br />
</span></span> </div><div><pre class="prettyprint" style="font-size: 10px">0b0000000 0
0b1000111 G
----------
0b1000111 XOR output
0b1010000 P
----------
0b0010111 XOR output
0b1000111 G
----------
0b1010000 XOR output
0b1000111 G
----------
0b0010111 XOR output
0b1000001 A
----------
0b1010110 XOR output
0b0101100 ,
----------
0b1111010 XOR output
0b0110001 1
----------
0b1001011 XOR output
...
0b1010000 XOR output
0b0110000 0
----------
0b1100000 XOR output
0b0110000 0
----------
0b1010000 XOR output
0b0110000 0
----------
0b1100000 Our checksum (96 decimal, 0x60 HEX)
</pre><br />
<div>As you can see, we ended up with '0x60' which is the same as our example sentence above of '*60'. So we were able to validate this NMEA sentence!<br />
<br />
<h3>NMEA Checksum Python Code</h3></div></div><div><br />
</div><div>Now that we got the explanation out of the way, let's look at the code. It's really simple:</div><div><pre class="prettyprint" style="font-size: 10px">def chksum_nmea(sentence):
# This is a string, will need to convert it to hex for
# proper comparsion below
cksum = sentence[len(sentence) - 2:]
# String slicing: Grabs all the characters
# between '$' and '*' and nukes any lingering
# newline or CRLF
chksumdata = re.sub("(\n|\r\n)","", sentence[sentence.find("$")+1:sentence.find("*")])
# Initializing our first XOR value
csum = 0
# For each char in chksumdata, XOR against the previous
# XOR'd char. The final XOR of the last char will be our
# checksum to verify against the checksum we sliced off
# the NMEA sentence
for c in chksumdata:
# XOR'ing value of csum against the next char in line
# and storing the new XOR value in csum
csum ^= ord(c)
# Do we have a validated sentence?
if hex(csum) == hex(int(cksum, 16)):
return True
return False
</pre><br />
There you have it!</div><div><br />
</div>doschmanhttp://www.blogger.com/profile/00219948412523833756noreply@blogger.com6tag:blogger.com,1999:blog-27141794.post-75000502963392636942013-01-05T18:46:00.000-06:002013-01-05T18:51:14.095-06:00Parsing NMEA sentences from GPS with Python + PySerialI've had a need to parse some NMEA output on my Raspberry Pi for a project I'm working on. In essence, it is pretty trivial to read from a serial port and parse ASCII data in any programming language, but to build some resiliency and efficiency in need to be handled with some care.<br />
<br />
I happen to interfacing with an EM-408 GPS module with my Raspberry Pi off the GPIO Rx/Tx USART GPIO pins.<br />
<br />
If you need a quick reference for NMEA sentence standard, go <a href="http://www.gpsinformation.org/dale/nmea.htm">here</a>.<br />
<br />
<h3>Working with PySerial</h3><br />
Below is a quick and dirty code sample to interface with a USART/serial interface. The biggest thing to take into consideration is the 'timeout' option when creating your serial.Serial() object.<br />
<br />
From my trial and error process, specifying timeout=0 (e.g. no blocking at all), while makes some sense in a GPS NMEA sentence polling application to return immediately and keep reading output, it causes serious amounts of CPU overhead (almost 100% utilization).<br />
<br />
Eliminating the timeout altogether (wait forever) isn't a great idea either because your code will endlessly block/wait for output from the GPS module; not good if the module ever dies/power loss/etc. <br />
<br />
Setting a gracious timeout of 5-10 seconds (e.g. timeout=5 or timeout=10) seems to help out as well and end up being the best of both worlds.<br />
<br />
Here's a snipit of my class for the EM-408:<br />
<br />
<pre background-color="#FFFFFF" class="prettyprint">import serial
class EM408GPS:
def __init__(self, serialport, baudratespeed):
self.gpsdevice = serial.Serial(port=serialport, baudrate=baudratespeed, timeout=5)
self.init()
def init(self):
if self.isOpen():
return True
return False
def open(self):
self.gpsdevice.open()
def isOpen(self):
return self.gpsdevice.isOpen()
</pre><br />
That rough class sketch should be a perfect class wrapper to get you going with interfacing with a GPS via serial port or USART pins on the Pi.<br />
<br />
<h3>Reading data with PySerial: Buffer or Newline?</h3><br />
This was the most interesting piece so far with. PySerial has a handful of methods for reading data that I tested with: <br />
<br />
<li> read(): This method reads the <i>size</i> of bytes from serial port input buffer.<br />
<li> readline(): This method reads serial port data down until a "\n" (newline) character is observed, then returns back a string.<br />
<br />
To be clever and witty, you'd generally <i>want</i> to use something like readline() since each NMEA sentence that it output to the serial port is terminated with a CRLF, right? I mean, why the hell wouldn't you? The answer is <b>wrong</b> the second you notice the very high CPU utilization happening when reading data.<br />
<br />
The good thing is this isn't a new problem, as it's a documented quite extensively on <a href="http://stackoverflow.com/questions/1328606/python-pyserial-and-cpu-usage">stack overflow</a> amongst other places. <br />
<br />
The better way I found to attack this CPU utilization problem, is to take advantage of another method that PySerial offers:<br />
<br />
<li> inWaiting(): Return the number of bytes currently in the input buffer.<br />
<br />
...and used this in combination with reading just '1' byte with read() then read whatever is left in PySerial's input buffer, then return for me to parse.<br />
<br />
Here's my class method called 'readBuffer()' partly solves this issue:<br />
<br />
<pre class="prettyprint">def readBuffer(self):
try:
data = self.gpsdevice.read(1)
n = self.gpsdevice.inWaiting()
if n:
data = data + self.gpsdevice.read(n)
return data
except Exception, e:
print "Big time read error, what happened: ", e
sys.exit(1)
</pre><br />
The next part to deal with is now that we are reading everything out of the input buffer, our NMEA sentences aren't <i>exactly</i> in sentence order anymore. <br />
<br />
Now we have to leverage a bit of coding to properly find the start and end of a NMEA sentence. It's not too bad of an effort since we know a NMEA sentence starts with a '$' and ends with 'CRLF'. The key point is to find the CRLF in your read data buffer, then ensure to use the right end of that CRLF split (which is the start and some data of your other NMEA sentence) as the new start of the data buffer to construct the next line until you find the next CRLF, and so on...<br />
<br />
Here's the code snipit from my main() area that shows the initialization of the GPS and the read out of the NMEA sentences from my readBuffer() method:<br />
<br />
<pre class="prettyprint">import re
...
def main():
device = EM408GPS("/dev/ttyAMA0", 4800)
newdata = ""
line = ""
while device.isOpen():
# If we have new data from the data CRLF split, then
# it's the start + data of our next NMEA sentence.
# Have it be the start of the new line
if newdata:
line = newdata
newdata = ""
# Read from the input buffer and append it to our line
# being constructed
line = line + device.readBuffer()
# Look for \x0d\x0a or \r\n at the end of the line (CRLF)
# after each input buffer read so we can find the end of our
# line being constructed
if re.search("\r\n", line):
# Since we found a CRLF, split it out
data, newdata = line.split("\r\n")
print "----" + str(datetime.datetime.now()) + "----"
print data
print
# Reset our line constructer variable
line = ""
</pre><br />
<br />
Below is graphed output from 'vmstat' on the Raspberry Pi (in 2 second intervals) showing the performance benefit from using readBuffer() approach with read() + inWaiting() vs. using PySerial's readline():<br />
<br />
<div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiTzz5v3f8Ggam5tsrD_wY314TFIkUK0VKgTDaoDePh1esBkJhVyWnDr0hKD1FhEWOXccj7s9xF2hHpOgJB4oBXHkIPPFUdtwnkjcGprfyeurDwnIiovrBIRkPhSeItuBafpvyQ/s1600/pyserial_rb_rl_performance.png" imageanchor="1" style="margin-left:1em; margin-right:1em"><img border="0" height="186" width="400" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiTzz5v3f8Ggam5tsrD_wY314TFIkUK0VKgTDaoDePh1esBkJhVyWnDr0hKD1FhEWOXccj7s9xF2hHpOgJB4oBXHkIPPFUdtwnkjcGprfyeurDwnIiovrBIRkPhSeItuBafpvyQ/s400/pyserial_rb_rl_performance.png" /></a></div><br />
<br />
<br />
doschmanhttp://www.blogger.com/profile/00219948412523833756noreply@blogger.com4tag:blogger.com,1999:blog-27141794.post-16350154102020224272012-11-25T21:43:00.000-06:002013-01-05T20:31:14.531-06:00Motorola Oncore UT+ Interface and PPS Breakout Board + SchematicsI've been a long dabbler of all things 'network time' related for 5+ years now and do maintain a fair number of stratum-1 time sources for myself (two Motorola Oncore UT+, one Trimble Thunderbolt and soon-to-be WWVB). I shouldn't be that selfish and really make them a part of the NTP public pool; we'll see. <br />
Out of the several hobbyist-affordable time sources to obtain (Garmins or any NMEA-output), I do think the Motorola Oncore UT modules are pretty top-notch in terms of reliability, stability and performance. I think it provides just the right amount of challenge and barrier-to-entry for anyone who wants to dabble in EE and do some TTL-to-RS232 logic shifting to get one of these to work. <br />
<br />
<h3>
Reasoning Behind This</h3>
1) <b>Arrangement and un-honkify my setup:</b> To nicely arrange the Motorola Oncore module with a MAX232 and a battery for backup onto some sort of prototype perf board. For the LONGEST time (3+ years), I had an individual TTL-to-RS232 DB9 breakout screwed to some wood, and used a DB9-serial ribbon cable (since the Motorola Oncoreh has a 10-pin male header and the DB9-serial conveniently has a 10-pin female socket + ribbon). I'm no engineer, but I like to pretend to be one on my spare time (and at work when I'm allowed to) but I thought it was about time to make my stuff look a little bit more professional and less honky. <br />
2) <b>No onboard battery for almanac storing with power-loss:</b> My UT+ modules do NOT come with an onboard battery, thus every time I'd lose power, the cold-start time on the GPS was enough to piss me off from time to time. I used to have a UPS but kW usage over time really added unnecessary 'cost' to my electric bill to the point where I could really live without forking over several hundreds of dollars to 'the man' a year for the few times I lose power intermittently. <br />
3) <b>Constant falseticker issues with current hardware setup and PPS from Motorola:</b> For whatever reason (and I think partly due to newer ntpd versions, see <a href="https://groups.google.com/forum/?fromgroups=#!topic/comp.protocols.time.ntp/9lmJo66BSLU">this post</a>) ntpd would label my PPS timesource as a falseticker all the time and it was frustrating. I didn't want to do some configuration hack and force truechimer status with 'true' in the ntp.conf config. What I was currently doing is sending the 1PPS TTL signal straight to DB-9 Pin 1 (carrier Detect) on the assumption that RS-232 logic is 3-24v, so clearly +5v TTL would 'barely' fall into it that logic path, but would. After some forum posting, I decided to move the 1PPS signal through the MAX232 TTL-to-RS232 shifter as well and my current circuit only took two inputs; one for Rx and Tx. So a redesign was needed. <br />
4) <b>Get the RS232 DB-9 serial output and antenna to be in the same location:</b> Right now I plug my DB-9 serial cable in on the right side then the antenna is on the opposite side so it makes positioning this thing in my closet hard with my crappy setup. <br />
<br />
<h3>
The 'Solution' (so far)</h3>
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgaN2dTSQR8eVFd7LeoKSoywXZU4GOHj_JShe-6yMo-ru4sY2DHzOqs4KfFYJudMKMAPXwOPElMsUrpNUVxzLvY3oQ81naZ8UDGPbzyiN_8tYsfKYSfqBZMIK1lAO_ECE6lJsl5/s1600/motorola-oncore-interface+%25282%2529.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="232" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgaN2dTSQR8eVFd7LeoKSoywXZU4GOHj_JShe-6yMo-ru4sY2DHzOqs4KfFYJudMKMAPXwOPElMsUrpNUVxzLvY3oQ81naZ8UDGPbzyiN_8tYsfKYSfqBZMIK1lAO_ECE6lJsl5/s400/motorola-oncore-interface+%25282%2529.png" width="400" /></a></div>
This certainly isn't complicated at all. Biggest time waster on this is: <br />
1) Soldering time --- take a while to solder all that together when it's thru-hole. <br />
2) DESIGN!!!: Because I wanted this to 'snap' together and sit on the underside of the UT module, I had to really think about this. I certainly didn't plan it out as nice as I turned out (I think). Here's another few pictures of me putting it together, along with the final product, and how it fits together underneath the Motorola Oncore module: <br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjiL5tWLCnBrYdWgSRs5WwxC4SUM1AwTIRsZrmm2rojmUwv8L8pexbweUqZzsU4MVY9L_hA7j3VQeI3K54ksXkaNN8ob6VenK4_1tSzteMcQeH9A3dx8rEJlXD9EivPDFh7phrk/s1600/Photo+Nov+23%252C+10+14+17+PM.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="400" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjiL5tWLCnBrYdWgSRs5WwxC4SUM1AwTIRsZrmm2rojmUwv8L8pexbweUqZzsU4MVY9L_hA7j3VQeI3K54ksXkaNN8ob6VenK4_1tSzteMcQeH9A3dx8rEJlXD9EivPDFh7phrk/s400/Photo+Nov+23%252C+10+14+17+PM.jpg" width="299" /></a></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjliBe5u1FF_e9I06CBbXf0YEV2t7DsCjgtWj839rmxmJMXIFaX03oYC0bUTd7Fo4FT8IBeyNatnt7ww0hptUsTaW0Z6PN4pOrvReoH1v5teFRdnbjG3ivPCP1zr4vhcLHQRRb1/s1600/Photo+Nov+24%252C+12+06+33+AM.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="400" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjliBe5u1FF_e9I06CBbXf0YEV2t7DsCjgtWj839rmxmJMXIFaX03oYC0bUTd7Fo4FT8IBeyNatnt7ww0hptUsTaW0Z6PN4pOrvReoH1v5teFRdnbjG3ivPCP1zr4vhcLHQRRb1/s400/Photo+Nov+24%252C+12+06+33+AM.jpg" width="299" /></a></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhGWTf1WzngK0RlMoF5j9Oo8iIlmNlgEKQtAFYQOQgZd06gBxPp0I6PNOBsD9FF55hyphenhyphenRsIxuRI-8WZ6f-cGH79aD_tncVmJql6aPTupx3dO4Lo6JEySLFoWFp5eigOtvDyrL-Kw/s1600/Photo+Nov+24%252C+12+54+40+AM.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="299" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhGWTf1WzngK0RlMoF5j9Oo8iIlmNlgEKQtAFYQOQgZd06gBxPp0I6PNOBsD9FF55hyphenhyphenRsIxuRI-8WZ6f-cGH79aD_tncVmJql6aPTupx3dO4Lo6JEySLFoWFp5eigOtvDyrL-Kw/s400/Photo+Nov+24%252C+12+54+40+AM.jpg" width="400" /></a></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg8tWu-cTTkEvBOVbJVhPOKrmHdeajGj0DqDpTjXiTTFPjV55eymqEWvnq-oqIlGg5ol6m4KpxNOsxOJ6gm3tCy7b5UuWi3rsvP3fs3NYZrbhwb1oB_P5_3sIk1JgUNedAqwra0/s1600/Photo+Nov+24%252C+11+45+45+AM.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="400" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg8tWu-cTTkEvBOVbJVhPOKrmHdeajGj0DqDpTjXiTTFPjV55eymqEWvnq-oqIlGg5ol6m4KpxNOsxOJ6gm3tCy7b5UuWi3rsvP3fs3NYZrbhwb1oB_P5_3sIk1JgUNedAqwra0/s400/Photo+Nov+24%252C+11+45+45+AM.jpg" width="299" /></a></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhiYo98WiNb-MiTTU3zTGjjTodilGZTnhX9IjwHc2kvR0nogpmr8BLFYXwpqk5gLUR5CUocpS4Err2D0uAi1nKhSmY_5It3PUTvgRghbV7uxX2-zwiNgffHeQhzpXD7QjpITT8H/s1600/Photo+Nov+24%252C+11+47+24+AM.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="299" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhiYo98WiNb-MiTTU3zTGjjTodilGZTnhX9IjwHc2kvR0nogpmr8BLFYXwpqk5gLUR5CUocpS4Err2D0uAi1nKhSmY_5It3PUTvgRghbV7uxX2-zwiNgffHeQhzpXD7QjpITT8H/s400/Photo+Nov+24%252C+11+47+24+AM.jpg" width="400" /></a></div>
<br />
<h3>
Parts List</h3>
Since I did my schematic with <a href="http://www.digikey.com/schemeit">Digikey's scheme-it</a>, I was able to make a nice bill of materials in case someone else wants to dupe this. I'm not endorsing Digikey, but you'll be able to see what I used; I had all these parts on hand from years of accumulation.<br />
<br />
<pre class="prettyprint"><span style="background-color: white;">Object Name Value Digikey Part #
R1 RESISTOR 1k8 CF14JT1K80CT-ND
R3 RESISTOR 470k CF12JT470KCT-ND
R4 RESISTOR 330k CF18JT330KCT-ND
J2 2X5 952-1924-ND
J3 9-PIN, FEMALE A32510-ND
IC1 IC MAX232CPE MAX232CPE-ND
C1 NON 1uf P4537TB-ND
C2 NON 1uf P4537TB-ND
BT1 BATTERY HOLDER CR2032 BU2032SM-HD-GCT-ND
J4 1X2 TMS-104-02-S-S-RA-ND
C3 NON 1uf P4537TB-ND
C4 NON 1uf P4537TB-ND
R2 RESISTOR 1k8 CF14JT1K80CT-ND
L1 LED Red 751-1089-ND
L2 LED Green 51-1105-ND</span>
</pre>
Get whatever type of thru-hole prototype perf board you want; I had some leftover stock I picked up from Radioshack a long time ago. <br />
<br />
<h3>
Improvements To Add</h3>
1) Put some inline diodes for some circuit protection along with a 5v voltage regulator --- I'm under some wild assumptions that I'm the only one who will ever use this and always apply 5v DC supply to it. <br />
2) Still work on that battery indicator just because after I stuff this up in my closet, it gets easily forgotten. I stumbled across this for a <a href="http://streampowers.blogspot.com/2012/08/3v-low-battery-voltage-flasher.html">3v low battery flasher using a Panasonic MN13811-G</a>, but that MN13811 was pretty hard to find anywhere (digikey, mouser, etc.) <br />
3) Get it off the wood 1x4 mount and get a proper project box to enclose this. <br />
<br />
<h3>
NTPd info</h3>
Here's a snapshot of my tuned ntp.conf for the Motorla Oncore UT's (in case you need a jumpstart on it): <br />
<br />
<pre class="prettyprint">enable pps
pps /dev/oncore.pps.0 hardpps
# Oncore Motorola UT+
server 127.127.30.0 minpoll 6 prefer
fudge 127.127.30.0 time1 0.1988
# Oncore Motorola UT+ 1PPS on DCD
server 127.127.22.0 minpoll 6 prefer
fudge 127.127.22.0 time1 0.39726
tos mindist 0.010
</pre>
Here's a look at my peers listing: <br />
<br />
<pre class="prettyprint">$ ntpq -p
remote refid st t when poll reach delay offset jitter
======================================================================
LOCAL(0) .LOCL. 8 l 486 64 200 0.000 0.000 0.000
*GPS_ONCORE(0) .GPS. 0 l 3 16 377 0.000 0.010 0.003
oPPS(0) .PPS. 0 l 34 64 377 0.000 0.099 0.133
$
</pre>
<br />
<h3>
Resources</h3>
A few sites of interest I referenced and used for the idea: <br />
1) TAPR Motorola Oncore Interface SemiKit (<a href="http://www.tapr.org/gps_vpib.html">http://www.tapr.org/gps_vpib.html</a>): I'm sure I've looked at this while re-referencing the Motorola Oncore manuals from here, but this is EXACTLY what I wanted to do. However, I'm not going to pay to get boards made, nor do I want to have an all-fitting Motorola Oncore interface board; I just have UT's. <br />
2) Simple low battery indicators (<a href="http://kyorune.com/modding/article.php?id=55">http://kyorune.com/modding/article.php?id=55</a>): This is very, very barebones. However, it gave me a good opportunity to do some testing, even though I kind of knew a head of time this was going to be too expensive milli-amp wise on the battery to even make it useful. The Motorola draws in micro-amps, so the the added value of an LED drawing at milli-amps just makes no sense.<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
doschmanhttp://www.blogger.com/profile/00219948412523833756noreply@blogger.com0tag:blogger.com,1999:blog-27141794.post-67191294278322830692011-09-02T21:05:00.003-05:002018-04-17T20:20:44.639-05:00MP3 Oompa Loompa GrillI consider it a good thing when certain individual consumable and/or usable products that were made separate from each-other are united and combined. Macaroni-and-cheese, PB&J, and the Toaster-oven come to mind. However, I think there's a lot to be said about the staggering amount of shit in this world that does not belong together. Ever. Period.
<br />
<br />
My neighbor shouted over to me this evening with great excitement in his voice. "Adam, do you want to see something cool?". Now, I do agree that there is a certain level of bottom-line expectation that must be considered coming from anyones neighbor.
<br />
<br />
I was surprised to find out my neighbors newfound, prized possession wasn't a big wooden box stamped with "fragile" all over it and it sure as hell wasn't from France. What he shouted out to me was probably the dumbest fucking thing I have heard to date: Mini-gas, MP3-ready outside cooking grill with speakers ...and a thing which tells time.
<br />
<br />
What posses a person to invent such a jack-shit product is an entirely different topic of discussion. What really gives me a ball ache on this one is peoples sense of mystique and gravitation towards items like that?
<br />
<br />
Maybe next time I suggest he just take fistfuls of leftover money and just toss it up into the air on a windy, South Dakota day. Perhaps I urge him to come clean with his Trailer Park Boys 'Randy' Cheeseburger fetish. Or maybe he just likes to eat mini cheeseburgers off naked midgets.
<br />
<br />
The odds of us both benefiting from any events like that are much higher than me giving a hot, peppered shit about the next innovative, chinese wet dream he brings home from Menards.
<br />
<br />doschmanhttp://www.blogger.com/profile/00219948412523833756noreply@blogger.com0tag:blogger.com,1999:blog-27141794.post-45172924429341311262011-08-31T19:48:00.001-05:002011-08-31T19:48:44.218-05:00SSD in the Laptop!I finally decided to break down and get an SSD for my main, full-size laptop. I've been through the growing pains of an SSD over a year ago when I put on in my Acer AspireOne net boom and was really pleased.<br /><br /><br /><center><a href='https://picasaweb.google.com/101867538374964328812/DoschManSBlog?authkey=Gv1sRgCOPZksHMqZb7YQ#5647186732767439618'><img src='https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiKLlOnRwtePDWhfZz9VDOnHyCmjI3Lk8XbGMGPNwKB_uytm1C5t94jCIHOoH8w4WpOny9gWtVw1DyjAulmtG01cn3SEYUE729g6HotnoODdQqzlvzI0NXA-Du2HkvYm9ga0Mws/s288/0.jpg' border='0' width='400' height='400' style='margin:5px'></a></center><br />So here's to an evening of performing a backup/restore and hopefully see some need disk bandwidth as the result.<br />doschmanhttp://www.blogger.com/profile/00219948412523833756noreply@blogger.com3tag:blogger.com,1999:blog-27141794.post-16101785686576085122011-08-28T17:41:00.001-05:002011-08-28T17:42:29.771-05:00The Curse of "Noodle Man"The curse of the "Noodle Man" has been a crushing blow to today's rising youth. The "Noodle Man" will stifle, demean, delay and counter-measure the educational needs of your child without remorse and perform his dastardly disservice at any cost.<br /><br />Despite the elated "Noodle Man" name, that's quite a laundry list of devious activities to be carried out by one being that would have a ripple effect over such a wide spectrum of people, especially of children and the future of our world.<br /><br />I, being a parent, would find some alarm in this. So, who is this "Noodle Man" and how can I stop him?<br /><br />For the minority of decent people and parents in this world: you fucking don't. The "Noodle Man" is a figment of imaginative proportions; a conjured up joke; a tall tale; a lie. He doesn't exist. However, the majority of Darwin-ducking, breeding Neanderthals... The "Noodle Man" is very real.<br /><br />When I observe kids who are 10 and 11 years old, still in 4th grade and cant read compound words (not even sentences), the "Noodle Man" is a shared name for mom and dad who don't spend ample time with them to foster a good attitude, not to mention succeed in school and life.<br /><br />One of my kids' friends were over this weekend and they asked me, "What is 'Noodle Man'?" My reaction was confused, followed by the response, "What are you talking about?". I was directed to look at the side of a pizza box we had on our kitchen table. What came next was a clear WTF moment (see picture). I just shook my head and said, "Are you sure that's what it says?". I wouldn't have had a problem except for the kids immediate chatter back, "Ha ha, I don't know how to read at all and I don't care.".<br /><br /><br /><br /><br /><center><a href='https://picasaweb.google.com/101867538374964328812/DoschManSBlog?authkey=Gv1sRgCOPZksHMqZb7YQ#5646040658413176658'><img src='https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgrjvo8aM79cx1ZdNGCPAjWPa5MeAwV7dqhTamGRy7pJjl7ITDTXCQRRs01ZSvSWlE-ZyXObk56LaYhP7B4GN5fwjBxLUwtGR4DmZyHdsiT0UEHEqcWmBgJUUauum2hOf8lIQiT/s288/0.jpg' border='0' width='281' height='210' style='margin:5px'></a></center><br /><br />So lets do our children a favor everyone and brig them up in an environment where success, satisfaction, self worth, education and intelligence are held to just a slightly higher standard than TV, video games, laziness and mediocracy.<br /><br />doschmanhttp://www.blogger.com/profile/00219948412523833756noreply@blogger.com0tag:blogger.com,1999:blog-27141794.post-42835688496858440232010-02-09T16:29:00.003-06:002010-02-09T16:59:13.148-06:00Bad Publicity for Operation Iraqi Freedom VeteransI came across this <a href="http://www.cnn.com/2010/CRIME/02/08/washington.soldier.charged/index.html" target=new>article</a> today about an Operation: Iraqi Freedom Army veteran who has been incarcerated for physically abusing his 4 year old daughter.<br /><br />Now, unless you know me personally, it's probably the last thought in your mind that I would be an Iraq war veteran. Well, I am. I did my time and put foot-to-ass for stars-and-stripes and to bring it to conclusion: If anyone is aloud to have an voiced opinion about the OIF/OEF war and it's branches of topics, we, as veterans, certainly do before anyone else. <br /><br />All pride and militaristic views a side, I have just three words of shear, and utterly blunt truism to say about this article: absolutely-fucking-ridiculous. <br /><br />Everyone I know (including myself) experienced a tough time during deployment and with adjustment coming home. To have some enlisted Army puke to water-board his kid for not getting the ABC's right is outright lunacy. Seriously, drop the big, tough Army guy pose and use your VA benefits to go see mental health and hug it out, bitch. <br /><br />I don't have any respect for this guy and I think he should get the stiffest penalty. Let's just hope the military doesn't try and protect him by hiding him on base and let this pass as some PTSD issue. To me, this is NOT a PTSD issue, but some guy being a dipshit and now blaming it on PTSD.<br /><br />Drinking/Drug problems? Flashback of a horrendous experience or situation? Bad dreams? Loss of sleep? Avoidance? Blackouts? Ok, no issues with that. Beating up your family for some poor ass excuse? Not acceptable. <br /><br />I bet this poor excuse didn't punch his 4 year old when he got off the plane. I guarantee you they hugged, kissed, smiled, laughed, ect. So, to me, that's a clear determination you can separate your two environments (war and the 'real' world) in your head, since you didn't barrel role off the plane in fisticuffs and ventriloquist-like machine gun sounds. <br /><br />Even if I were to give this guy the benefit of a doubt and let's say he does really have PTSD and wasn't some joker E-5 or E-6 sitting in the air-conditioned command operations tent watching satellite TV and looking at porn on NIPR network. <br /><br />PTSD or not, everyone knows right from wrong. We all know the difference between reality and war. It may have been a culture shock from HELL for him to see his first car bomb/IED/dead body/casualties/bad situations/deprived Iraqis, but guess what, we all did. And guess what? We all drove on, and did what we need to do. You suck it up, stuff in the back of you head and move on. When you get back, it's time to go see someone and get it out of your system. You failed in every aspect of that category. And you can't say, "No one told me where I could get help", either.<br /><br />And let's not forget the out-process portion of deployments either. You *ARE* asked and *YOU DO* have the opportunities to talk to whomever you need to talk to about whatever subject you want. You're not asked once, or twice or three times. You're asked on a daily basis and reminded of it, because isn't that the military way to en-still their ways into you by repetition, brute force and tough love? Sure it is. That's what basic training is all about.<br /><br />I hope you go make big rocks into little rocks next to Michael Vick's old cell at Ft Leavenworth, you lose custody of your child and you get dishonorably discharged from the military. I think you waived all your rights to be called a veteran when you start giving the rest of us who did the same time you did a bad name.doschmanhttp://www.blogger.com/profile/00219948412523833756noreply@blogger.com1tag:blogger.com,1999:blog-27141794.post-3832536826702373842010-01-02T07:53:00.003-06:002010-01-02T08:09:08.521-06:00Brrrrrrrrrrrr! Are you Kidding me?!?!The weather this year has been out-of-this-world COLD! Holy crap! I've been a resident of South Dakota all my life and it does get cold here, but down to an <b>air temperature of -20 F</b>?! I think I just said 'South Dakota' in that last sentence, NOT Siberia.<br /><br /><a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhBE3YQiyGSONjtFxFjP8kyzBZB7w4Fu7L0GscHPq3CFYMYasQjhZBBD6HEyubNeOHH4aUvJtRCTIJo-PW9e4hejAr4wmAwQ5sCWke3OQ-6SAgrDt0IDCyIpScCYzZrWZh95_kZ/s1600-h/DS18B20_outside_1d_01022010.png"><img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 400px; height: 163px;" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhBE3YQiyGSONjtFxFjP8kyzBZB7w4Fu7L0GscHPq3CFYMYasQjhZBBD6HEyubNeOHH4aUvJtRCTIJo-PW9e4hejAr4wmAwQ5sCWke3OQ-6SAgrDt0IDCyIpScCYzZrWZh95_kZ/s400/DS18B20_outside_1d_01022010.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5422144061971993602" /></a><br />Above is a daily graph I make with `<a href="http://oss.oetiker.ch/rrdtool/" target=new>rrd-tool</a>` using Dallas 1-wire DS18B20 <a href="http://datasheets.maxim-ic.com/en/ds/DS18B20.pdf" target=new>sensors</a> I have around my house and outside. I'm just absolutely blown away; I've seen combined temperatures and wind speeds (wind chills) reach -20 to -40 F before around here, but it's just hard re-call actual air temperature reaching that.doschmanhttp://www.blogger.com/profile/00219948412523833756noreply@blogger.com0tag:blogger.com,1999:blog-27141794.post-57399679061015771592009-08-31T15:34:00.002-05:002009-08-31T15:53:37.213-05:00`make bowel-growl`?I've been really bad this last week with watching my diet. Maybe for the average 'Joe XL', eating out 2-3 times a week is a normal occurrence, but for this guy, it damages my damn body to a point of reckoning. Ya, so maybe I sound like a fucking sissy poster boi for an "Activa" commercial... case in point: I'm not a fast food or restaurant devotee; I'd prefer to make my own healthy food and eat in moderation.<br /><br />This morning was an absolute test in gurgling intestinal foo. A sudden urge to drop the brown snake anchor hit me like a ton of bricks. So what's a geek like me to do when I know I'm going to be stranded in the handi-capped john stall for a while? Well, a dude like me grabs the nearest book within reach and heads for the can.<br /><br />Well, out of all books I happened to grab, I took the convenient, yet coincidentally ironic book title of '<a href="http://oreilly.com/catalog/9780937175903/">Managing Projects with Make</a>' by O'reilly.<br /><br />What did I learn from all of this? Well I certainly didn't learn how script myself to do a 'make dump' or anything impossibly fantastic, but I did train myself to keep a better set of bathroom-friendly material in case I have another attack of the eatting-out-bowel monster.doschmanhttp://www.blogger.com/profile/00219948412523833756noreply@blogger.com0tag:blogger.com,1999:blog-27141794.post-52211096789111299152009-02-27T06:42:00.002-06:002009-02-27T06:52:11.065-06:00One day sunny is another day... snow<a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEirOS2bWq9qf1HXzyaG857lMnRWeJiqsl3Xlw3va2aLFPHX5q6HQwJj1vNLRW-XK7fTA5c8b32I8UGg8M4NPPw4M9B1jSAK5JwTJ10qblDIeT4C15sqvh_M6VcJBzPdkwI9Jddf/s1600-h/P2260165.JPG"><img style="float:left; margin:0 10px 10px 0;cursor:pointer; cursor:hand;width: 320px; height: 240px;" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEirOS2bWq9qf1HXzyaG857lMnRWeJiqsl3Xlw3va2aLFPHX5q6HQwJj1vNLRW-XK7fTA5c8b32I8UGg8M4NPPw4M9B1jSAK5JwTJ10qblDIeT4C15sqvh_M6VcJBzPdkwI9Jddf/s320/P2260165.JPG" border="0" alt=""id="BLOGGER_PHOTO_ID_5307456972479922706" /></a><br />Living in the highly fluctuating, climatic state that I live in, it's a wonder than the population isn't lower than it already is. It's almost a trip on borderline depression! How the hell is it possible to go from taking a country-side hike with a short sleeve t-shirt and sunglasses, writing some melodies with my acoustic guitar on the deck with a cup of tea all in the sunset balance of a warm, soothing 59 degrees, to digging my winter garb out of the closet to cope with the four blistery inches of snow and a -10 degree air temperature (not counting in the wind)?<br /><br />*Sigh* Where else on the planet could you get such sweet diversity?doschmanhttp://www.blogger.com/profile/00219948412523833756noreply@blogger.com0tag:blogger.com,1999:blog-27141794.post-30870190774105655182009-02-26T13:31:00.002-06:002009-02-26T14:12:10.450-06:00Heroin Addict Heroes on my iPodOver the last couple of months, my iPod album playlist has kind of evolved with my recent rekindling of acoustic tonal love. The downside of only having 8GB to work with on my 2Gen nano is that I can't house the entire coffee-house spectrum of music I want to listen to without putting a sizable dent in my rock repertoire. <br /><br />I can't help but express another one of my complains: The music arena this decade sucks total shit and I don't see it getting any better any time soon. I grew up on way late 70's, 80's, and early to mid 90's pop/rock/metal side of the tracks; when bands had their own image and weren't cookie cut out to fill a marketing gap and hellbent on polluting the airwaves with more scr(emo) and shitty power chord thrashing.<br /><br />So, perhaps my album highlight is overpowered by the fact that every one of the lead singers in these bands have died of heroin abuse.<br /><br />Here's the top three this week:<br /><br />1) <a href="http://www.amazon.com/Apple-Mother-Love-Bone/dp/B0000AJ5S0/ref=sr_1_2?ie=UTF8&s=music&qid=1235678706&sr=1-2">Mother Love Bone - Apple</a><br /><br />2) <a href="http://www.amazon.com/Blind-Melon/dp/B000002UY5/ref=sr_1_1?ie=UTF8&s=music&qid=1235678809&sr=1-1">Blind Melon - Blind Melon</a><br /><br />3) <a href="http://www.amazon.com/Sap-Alice-Chains/dp/B0012GMUSQ/ref=sr_1_8?ie=UTF8&s=music&qid=1235678829&sr=1-8">Alice in Chains - Sap</a><br /><br />...these bands need no explanation. They just a very small example of what was good in the music industry when I was growing up.doschmanhttp://www.blogger.com/profile/00219948412523833756noreply@blogger.com0tag:blogger.com,1999:blog-27141794.post-30171424845770120632009-02-15T08:06:00.002-06:002009-02-15T08:10:12.945-06:00Another affirmation Social Networking is G-A-YYet another credible blog article on the dark facts of social networking and it's infinite stupidity and misconceptions surrounding your so-called "network of friends":<br /><br /><a href="http://scitech.blogs.cnn.com/2009/02/13/are-you-a-facebook-friend-padder/">Are you a Facebook friend padder?</a><br /><br />Lame.doschmanhttp://www.blogger.com/profile/00219948412523833756noreply@blogger.com1tag:blogger.com,1999:blog-27141794.post-56241316608956737192009-02-10T11:24:00.004-06:002009-02-10T11:46:23.551-06:00White-space removal goodness with LinuxI've been recently putting together a massive backup of all my digital wares on my network. Problem is, over the years, when I've converted any CD I had over to digital mp3's or made a copy of one of my DVDs, a lot of it was done without a lot of thought that I'd be backing it up to a UNIX box 9-10 years down the road; so a lot of the filenames by pure convenience to the application(s) I was using, uses white-spaces as delineations between fields on a filename.<br /><br />Is that a real problem? Kinda because white-spaced named files are a hooker to work with under *NIX platforms. Case in point, it does cost me some sleep at night. <br /><br />So where does Adam go when there's no where else to turn? the *NIX command-line.<br /><br /><blockquote><br />sed example: sed -n "s/\s/_/g"<br /></blockquote><br /><br /><blockquote><br />tr example: tr [:space:] _<br /></blockquote><br /><br />...quick and dirty solution.doschmanhttp://www.blogger.com/profile/00219948412523833756noreply@blogger.com0tag:blogger.com,1999:blog-27141794.post-73307941398785615072009-02-05T14:08:00.006-06:002009-02-05T18:01:25.189-06:00Yet Another Reason Social Networking Technology is... gayIt happened again...<br /><br /><a href="http://www.cnn.com/2009/TECH/02/05/facebook.impostors/index.html">Fears of impostors increase on Facebook</a><br /><br />I'm not a fan of social networking. Never have. Never will be. To me, social networking is nothing more than a self-dwindling, sick, unrealistic sense of friendship, popularity and most importantly: a false impression of listening ears of people who give a shit.<br /><br />There's plenty of excuses why people use social networking. Any worthy excuse I've ever heard usually boils down to "keeping in touch". Stupid reason, at best. If you want to keep in touch with your friends, try 'human contact'. Any one I know who I've befriended has my personal home telephone number. I don't see how you can get more personal than that considering everyone on the planet in any urban-type area has a cell phone. <br /><br />Perhaps I'm old school or I just don't want to adopt douche-bag adaptations of so-called "great technology", but what happened to e-mail? *Everyone* has it. There's no way you can't have e-mail and even register for any social networking service. Last time I checked, e-mail attachments still worked and most of the working, urban world uses some sort of broadband connection, whether is be wired or wireless, or at home or know where to get access to it. To me, social network sites have pretty much reinvented the already turning wheel that message boards, newsgroups, e-mail distributions and instant messaging clients already have done for MANY years.<br /><br />I, myself, prefer my privacy, seclusion and "me" time. I don't give a shit about your twitter notification telling me where you are every 5 seconds of the day. Nor do I care if I hurt your feelings if I didn't "shout out" to you on your MySpace message board. I could care less what your likes and dislikes are; your favorite movies; the music you like; what damn high school you came from; why you can't relate to mommy and daddy anymore; what your sexual orientation is; why you choose the religion you do. To me, it's all a sick cry for attention, bragging rights and to get some face time on the internet.<br /><br />Insecurity makes you embrace social networking. If you had *real* friends, they'd already know the answers to all the intricate questions I mentioned above or that MySpace asks you in your profile. You wouldn't have to leave yourself bleeding in the wind for the whole world to see. <br /><br />On top of all this, think of all the depressed, confused and spastic people who spend hour after countless hour typing, posting, uploading photos, and keeping their profile up-to-date in hopes that they'll get one "virtual" nibble of friendship. Yes, virtual. Not *real*. I swear that social networking is in a close damn second with NCAA tournament in amount of time wasted. Take all that lost effort and put it into real, tangible friendships instead of a thumbnail photo and a lame profile I wouldn't trust any farther than I could throw it.<br /><br />In conclusion, on a internet social networking medium, my condolences. I think it's the worst technology this century has created.doschmanhttp://www.blogger.com/profile/00219948412523833756noreply@blogger.com3tag:blogger.com,1999:blog-27141794.post-5469486539410488992009-01-23T18:21:00.002-06:002009-01-29T20:17:22.309-06:00Poop Birds squatting on Mr Roger's inside shoes?<span style="font-weight:bold;">Poop bird</span> (<span style="font-style:italic;">n</span>): <span style="font-style:italic;">Funny combination of two nouns that just don't belong together, yet the linear conglomeration of them make comical consortum in my kids eyes.<br /></span><br />Early this morning, while getting ready to walk out the door for work, my kids are usually just getting up to start their day. As they trot up the stairs still in a sleep induced haze, they are usually cognitive enough to tell me good morning as I return a mere jester of my comical love. <br /><br />As soon as I utter, "Top 'o the morning poop birds," do I realize that I have done something to my youngest daughter. That 'something' was what all of us have gone though one time or another in our lives. That 'time' where that 'some thing' that you've heard or seen a million time before suddenly makes 'sense'. <br /><br />I've never seen more combustible laughter in my house like that before. It goes to show that when you observe your child finally understand and get humor is probably one of the best days of your life. <br /><br />On this very same day, I walked in the door as I normally do after a good ol' day at work, take off my 'outside' shoes and, routine, as always, put on a pair of nice, comfortable old man slippers. What's sad, is that it finally sunk in what I've been doing for the past year: I'm, in a very slight sliver of a way, finding myself putting reminiscent scenes from Mr Rogers in my life with one of them being having a pair of dedicated inside and outside shoes.<br /><br />In retrospect, I've found that as I'm not as old as I appear, life is worn on a good path in parts of my life. And as I find myself picking up old man habits well before 30, it's nice to know my kids still glow some of that youthful humor anyone with half a pulse can appreciate.doschmanhttp://www.blogger.com/profile/00219948412523833756noreply@blogger.com0tag:blogger.com,1999:blog-27141794.post-31116299879566174692009-01-03T14:29:00.003-06:002009-01-03T15:33:41.575-06:00Macgyver's Vengence Against Wal-mart?I've always had a personal disgust for Big Corporation, specifically Wal-mart. They'd wiggled their ways into our lives and we are all forced to succumb and bow our heads as we shuffle into fucking Wal-mart because it would be a financial stupor otherwise to go to 3-4 different places to conduct the same shopping experience because they stifle competition and harbor any chance local companies have to succeed without having to make their wares less competitive and more expensive.<br /><br />What Wal-mart provides in low prices and having everything in one general store location they uttery lack in a plethora of other categories: customer service, item availability, satisfaction, accountability, genuine item authenticity, ethics, morals and, point blank, doing what is right.<br /><br />So, why do I say all this? More importantly, what the hell does it have to do with Macgyver? <br /><br />Answer: a lot.<br /><br />I'm a big Macgyver fan, and I happened to have some gift card balance left and I needed one last season to complete my Macgyver DVD collection, so I ordered it on walmart.com. I went to pick it up at the local store late last evening and this morning I opened up the so-called 'newly' sealed DVD series of Macgyver.<br /><br />What I found in the DVD case was, well... a bit of shock and awe for me. All 3 DVD cases were shattered with plastic bits all over and the most bizarre bit of it all is 4 of the 6 DVDs had finger prints on them! (Yes, I said finger prints)<br /><br />I call Wal-mart customer service for walmart.com and they were certainly *not* helpful. I was told I could buy a new one again on their online shopping store and then on my own dime, return the DVD set to the store. Not an option for me considering I got shafted the first time buying from their online store.<br /><br />I then, in turn, called the local Wal-mart store customer service, which started out really promising, offering me exactly what I wanted: My money back so I could go buy my beloved Macgyver season somewhere else in town. I made it clear that they let the customer service department know the arrangement so I'm not wasting my time driving into the store to get the run around.<br /><br />When I got to my local Wal-mart store, it was a COMPLETELY different situation. Customer service pretended as if I had not called at all and told me I was stuck with only being able to exchange the item because I opened it. After stating that I've called already and getting confirmation I could get my money back because you didn't have that particular season in the store, I was then asked if I understood the quote/unquote "Federal Copyright Act". <br /><br />ARE YOU FUCKING KIDDING ME?! So not only was I getting treated like an asshole, I was also getting accused of somehow making copies of this Macgyver DVD series and trying to return it to the store. That was the deal breaker and I let loose on the obese, naive and obviously clueless customer service rep who obviously could have given two shits about listening to my situation nor cared enough to get the information on my arrangement I made prior to driving in.<br /><br />It's safe to assume that perhaps she didn't know about it, however, after getting quite pissed off at the fact that I was accused of DVD piracy, one of her co-workers said, "Hey, is that Macgyver Season 5?" The plump wonder I was dealing with, followed up sharply with, "Yes it is, Season 5 of Macgyver." <br /><br />...now this is where I finally got justice in a sarcastic sort of way. The co-workers then says, "That's already been approved, so give him his full refund back already." What sweet victory is was. <br /><br />What the fuck ever happened to the customer is always right? What ever happened to customer service being courteous and astute to customers? What ever happened to the commitment to customers? What ever happened to customer product satisfaction?<br /><br />The day I am done buying diaper pull-ups. baby wipes and other family items that otherwise are expensive in other stores are over, so are my fucking days of buying anything else at Wal-mart.doschmanhttp://www.blogger.com/profile/00219948412523833756noreply@blogger.com2tag:blogger.com,1999:blog-27141794.post-70305663434506630012008-12-07T16:16:00.003-06:002008-12-07T16:36:45.425-06:00Mac OS X 10.5.2 Leopard on a Dell Inspiron 531sI've been for quite some time on seeing what it takes to get Mac OS X (Leopard) running on Intel PC hardware. For the last couple of weeks, I've done nothing but research and being a troll on forums and happened to stumble across a forum post about troubles with Mac OS X and a Dell Inspiron 530/531s. Cool thing is I actually have a Inspiron 531s, so the quest begins to make it happen<br /><br />On several <a href=http://forum.insanelymac.com/index.php?showtopic=109542 target=new>posts</a> around the internet (most notably the insanelymac forums), there are claims that the 531s does/doesn't work, etc. <br /><br />I'm here to tell you it does work and I was successful in getting Mac OS X 10.5.2 Leopard Leo4Allv3 version installed. It isn't fabulous by any stretch of the imagination just yet, but I'll explain below.<br /><br />Just so it's not confusing or misleading, here are *my* hardware spec's on the Dell Inspiron 531s:<br /><br />* AMD Sempron 3600+ (2.0Ghz, 256K cache)<br><br />* NVidia Geforce 6150SE nForce 430 (on-board, using 256MB physical RAM for video memory)<br><br />* 160GB SATA Hdd<br><br />* 1GB DDR2 SDRAM @ 667Mhz<br><br />* 48x CDRW/DVD drive<br><br /><br />Below are the Mac OS X custom install settings for specific kexts I needed to enable to get it to <b>work</b>:<br /><br />* Kernel-9.2.0<br />* Third Party Drivers<br />--> Chipset Drivers > NforceTest<br />--> Graphics Drivers > NVidia Driver > NVinject Choices > NVinject Version 0.1.3 > NVinject 256MB<br />* ACPIPlatform<br />--> Old-ACPIPlatform<br /><br /><b>Installation Directions (really brief):</b><br /><br />1) I followed these directions almost verbatim, Click <a href=http://verafirmansyah.wordpress.com/2008/07/28/install-leopard-leo4allv3/ target=new>here</a> to see them<br><br /><br />2) When you get to the point in the Post-Install firstboot boot setup stuff where it asks "Do You Already Own a Mac?" when I would select the option "Do not transfer my information now" and click 'Continue' it would freeze temporarily and route me all the way back to the "Before You Begin" window. To fix that, I followed <a href=http://geekzine.org/2008/09/17/run-mac-os-x-on-an-eee-pc/ target=new>these</a> directions:<br /><br /> a) Booted into single user mode ( -s at the boot> prompt)<br /><br /> b) fsck'd the filesystem and mounted the filesystem read/write per directions when in single user mode<br /><br /> c) Followed the commands below to fake out the firstboot crap and get into the OS (per the wiki link above):<br /> <br /><blockquote> # /sbin/fsck -fy<br /> # /sbin/mount -uw /<br /> # touch /var/db/.AppleSetupDone<br /> # passwd root</blockquote><br /><br />On an operating system standpoint:<br /><br /><b>What Works:</b><br />* Well I can boot into Mac OS 10.5.2, yippie!<br />* NVidia 6150 at least works now and I get video, but it's really poor resolution<br />* CD-ROM<br /><br /><b>What Doesn't Work or isn't working (yet)</b><br />* On-board NVidia network card: I've found a <a href=http://forum.insanelymac.com/index.php?showtopic=12933 target=new>post</a> in insanelymac's form that I'm going to try this evening, but the Forcedeth/Forcedeth-V kexts from the install DVD did not discover my on-board NIC at all<br />* Have *no* idea how to get better results out of the on-board NVidia Geforce 6150. Right now, the only resolution I can do is 1024x768 and certainly no QE/CI. Any ideas?<br /><br /><b>What I haven't tested or am not able to test</b><br />* Audio: I think the video and NIC issue will consume most of my time right now. No sense adding more misery to the pile.<br />* Other network cards: I've read osx86 project's <a href=http://wiki.osx86project.org/wiki/index.php/HCL target=new>HCL</a> and I do have gob's of hardware, problem is that the Inspiron 531s take low-profile NIC's (which I have none of) I could very well put in a standard PCI 10/100 NIC (Intel Pro100, 3Com 905, etc.) but the case side won't go back on and that looks tacky as hell.<br />* USB devices: Much like the audio dilema, I'm concentrating on the video and LAN, so this will come after.<br /><br />So, I hope contributing this helps a lot of you out there. I'm horrible at maintaining posts and such, but I'm going to post this exact blurb on InsanelyMac (<a href=http://forum.insanelymac.com/index.php?showtopic=139933 target=new>Mac OS X 10.5.2 + Leo4Allv3 + Dell Inspiron 531s Success</a>) just in case I happen to forget to come back and post follow-up's to this.<br /><br />I scored my Dell Inspiron 531s for $150 from a co-worker WITH 4 months left on the original 1-year warrenty, so I'm pretty pleased that I might be able to get Mac OS X going on it!<br /><br />If any of you have any insight on some of the problems I'm experiencing, please feel free leave a comment!doschmanhttp://www.blogger.com/profile/00219948412523833756noreply@blogger.com0tag:blogger.com,1999:blog-27141794.post-72838066207188969772008-10-31T18:21:00.004-05:002008-10-31T18:36:54.519-05:00Fd Linux development starting again... finallyIt's been a *really* long time (approximately 7 years) since I've worked on my OSS project, <a href=http://www.fdlinux.com target=new>Fd Linux</a> and I'm finally starting to get my lazy ass in check and getting a bit more free time on my week[days,nights,ends] to get my development box set up and work on a new version of Fd Linux.<br /><br />It's kind been a quirky hiatus from this due to getting deployed to Iraq back in 2003 to 2005 and just getting back into the swing of things, along with getting a house, watching my two girls grow up, and been extremely busy with work. Life kind of gets in the way like that.<br /><br />Obviously over the years, the PC market has moved away from floppy disks (I honestly think floppy disk drives are *extra* commodities to add to PC's instead of defacto standards) and with solid state media dirt cheap right now and well capable of holding more than 1.44MB's worth of Linux goodness, it's a no brainer to start moving towards USB flash drives.<br /><br />Right now, I'm working on a side project that will help get the base started for Fd Linux development, which is a home-brew NTP server, running on a PCB-5825 (AMD Geode 300Mhz, 128mb PC-133), booting off of 256MB compact-flash and using a Motorola Oncore UT+ GPS module with PPS as it's time source. There's much more detail to that, but a lot of the rootfs generation groundwork from way back to Fd Linux v1.0.0 will be used to concoct a good setup for this project.<br /><br />Any rate, stay tuned. I'm pretty excited to get back into my groove.doschmanhttp://www.blogger.com/profile/00219948412523833756noreply@blogger.com0tag:blogger.com,1999:blog-27141794.post-10685668358116141832008-08-04T22:12:00.003-05:002008-08-04T22:38:51.120-05:00Sparkfun = Cool, Customer Service = BADI'm a geek when I want to be and I really dig tinkering with EE, gadgets and hardware. <a href=http://www.sparkfun.com target=new>SparkFun</a> is one of those places you could easily spend days dreaming up oodles of projects to put together.<br /><br />As much as I think they are cool, when a dude like me gets rubbed the wrong way one too many times from them, I tend to think otherwise. It all started back in Sept 2007; been looking for a breakout board for a GPS module I have and SparkFun had what I needed. I get the breakout board in the mail to find out there's design flaw on the board that won't even allow you to plug the certain GPS module I have into it. I contacted SparkFun, they owned up to the flaw and said they need to get rid of their current stock (which at the time was around 60-ish) so they can put the new stock up with the revision.<br /><br />Well... after several e-mails, many lies and false hopes that the *next* batch of breakout boards were the ones I needed with this so-called 'revised' fix, on July 30, 2008 (almost 10 MONTHS!) I was notified that the new revision was finally in and placed an order.<br /><br />Today, August 3, 2008, I get the long, awaited package. Do you think it was this breakout board for my GPS module? Nope. It was something complete different; something that wasn't even in the same fucking realm as to what I was expecting. It was like ordering a pizza and getting ape shit in box delivered instead.<br /><br />So I most certainly called immediately and what's really *odd* about this is, it's like they were expecting my call. I was transferred to the gentleman that apparently packaged and/or put together my order and the first thing he said was, "Here's your 2-Day FedEx tracking number for your item you didn't get. We'll be enclosing a return shipping label for the wrong parts we sent you.", all within the first 20 seconds of the conversation. It's like they were expecting me to call because of one two reasons: 1) Human error, or 2) They *said* that their PCB revision was in but it really is not, and did not have their run finished, so they sent me bogus shit in return to stall while their production run finished. You be the judge on the conspiracy theory... <br /><br />The point I'm trying to make here is: SparkFun has cool shit and I might buy from them again, but if they fuck up, don't expect them to win your heart and mind over.doschmanhttp://www.blogger.com/profile/00219948412523833756noreply@blogger.com0tag:blogger.com,1999:blog-27141794.post-8935957097197847982008-08-02T09:33:00.003-05:002008-08-02T09:45:57.089-05:00PAM max login limits in RedHat Enterprise 5I found something surprisingly 'odd' with pam_limits.so library when setting up and base lining a few servers the other day at work. <br /><br />For some reason you can not concurrently use both 'maxsyslogins' and 'maxlogins' at the same time in your /etc/security/limits.conf file to set max authenticated user/group logins per user or system. With my intentions of having a limits of anyone part of, lets say, the 'users' group, could not have more than 3 separate simultaneous logins into the box with a maximum hard limit of 15 total system logins just doesnt seem to work.<br /><br />So if you're going to try something like this:<br /><br /><blockquote><br /><font face=courier size=2 color=blue><br />@users hard maxlogins 3<br />* hard maxsyslogins 15<br /></font><br /></blockquote><br /><br />...didn't work for me. I have noticed, also, if you have a particular user who is part of several groups (e.g. users and devel groups) and you have limits for both of those groups, once the first group limits is matched, it goes with that rule. But if you have any idea on how to get 'maxlogins' and 'maxsyslogins' to work together, I'd be happy to know.doschmanhttp://www.blogger.com/profile/00219948412523833756noreply@blogger.com1tag:blogger.com,1999:blog-27141794.post-61557017306889012562008-06-16T21:35:00.007-05:002008-06-16T22:07:28.894-05:00Analyzing and cleaning out Linux/Unix filesystems that fill upSo I have this problem from time to time at work: bastid users or custom processes that either go rogue and start filling up filesystem space at an alarming rate, or crappy code that doesn't clean itself up.<br /><br />Here's a couple of my favorite commands to help out with that:<br /><br /><span style="font-weight:bold;"><font size=3>`find` Command</font></span><br /><br />If you aren't using `find`, you should. My favorite one-liners for stuff like this:<br /><br />Find all files in a directory with a size between (for example) 1KB and 10MB that last changed 1 minute(s) ago:<br /><br /><font face=courier size=1>[root@testbox]# find . -type f -size +1024k -and -size -10240k -cmin 1 -exec du -sb '{}' \;</font><br><br /><br />Find all files in a directory with a size at least (for example) 75MB that last changed 1 minute(s) ago:<br /><br /><font face=courier size=1>[root@testbox]# find . -type f -size +76800k -cmin 1 -exec du -sb '{}' \;</font><br><br /><br />Find all files in a directory with a size between (for example) 1MB to 100MB, owned by 'frank' (UID: 501) that last changed 1 minute(s) ago:<br /><br /><font face=courier size=1>[root@testbox]# find . -type f -size +1024k -and -size -102400k -uid 501 -cmin 1 -exec du -sb '{}' \;</font><br><br /><br />...the execution of `du` in my commands will definitely add some overhead, so feel free to leave it off. It's a nice quick human readable presentation if you're in a hurry, but I wouldn't do it if you have a shitload of files that are going match your search.<br /><br /><span style="font-weight:bold;"><font size=3>`lsof` Command</font></span><br /><br />Simply: list open files. This is your friend you can use in tandem with the `find` commands above to narrow down what process(es) are pillaging your filesystem. <br /><br />What I do is take the output of a particular find command if I see growing files out there but cannot narrow down what process(es) it could be and just simply run: <br /><br /><font face=courier size=1>[root@testbox]# lsof | grep <span style="font-style:italic;">file_name</span></font><br /><br />...where obviously, <span style="font-style:italic;">file_name</span> is some output you got from the `find` command(s).<br /><br />Those are just some of many tricks to do to track down that type of ridiculousness that happens when things go bad late at night when you're on-call.doschmanhttp://www.blogger.com/profile/00219948412523833756noreply@blogger.com0