Connect to CMS2000 solar inverter with LabVIEW and read power

After a few weeks of ‘chasing the sun’, finally got something I am happy with, LabVIEW connects to the CMS2000 via serial interface and reads the parameters.

Programmed as a state-machine, basic error checking and fail safes.

Note, I am using a RS232 to TCP/IP adapter, I am guessing a lot of the peculiarities are due to that.

Don’t use the thumb snippet, but the linked image.

Read CMS 2000 Inverter with LabVIEW

Read CMS2000 invert in LabVIEW VI

Phoenixtec (CMS2000) inverter protocols spreadsheet

DIN rail single phase two wire energy meter Lanx Australis LXEM180 manual

Here is the closest replication manual for the Lanx Australis LXEM180, which is available from Schnap

The manual is another rebadged version, operation is exactly the same.

DIN rail single phase two wire energy meter LXEM180-PRO2DM.pdf

LXEM180

AFS Walling Solutions – permanent formwork concrete walls review

Recently I did some research into the AFS Logic Wall product as an alternative to brick for a development I am working on.

AFS is a permanent formwork concrete wall solution, what this means is instead of creating the timber frame on site for the concrete pour, a factory creates a shell which is then assembled on site and filled with concrete.

The benefits are quicker wall construction times, days not weeks, as there is minimum site works. This initially seams like a huge benefit, but only after speaking to a number of industry people are the true costs discovered.

As a start, read through this AFS Assessment by the Ceramic Advisory Services, though the information may be outdated and biased.

I received the following information from an AFS distributor, April 2014;

Typically AFS150 would be supplied and installed and filled with concrete for approx $ 215/m2, ready for applied finishes.

Compared to a brick, the costs is fairly similar, especially if comparing to double brick. But there are some additional costs that are not accounted for.

From the distance, there looks like there is a huge advantage to reduced wall thicknesses, I was informed 150mm AFS could be used in place of my 230mm double brick. There are a couple of catches though, only electrical conduit can be set in the concrete, water pipes can’t and so a separate stud wall is needed, adding about 75mm and additional costs.

AFS wall have a specified insulation R value, though the wall is concrete only, if you can’t meet the required insulation then additional will be required. With double brick construction, the insulation can be installed in the cavity, there is no cavity with the AFS so again a separate stud wall is needed.

When you need a thin wall, brick is a minimum 90mm thick, whilst AFS is 110mm, possibly due to the cement formwork being 10mm in thickness on each side and unable to support any load.

The slab needs starter rebar for the formwork, whilst brick does not, again, adding additional costs.

Finally, there are only a handful of builders that work with AFS, in Perth I was given the names of four builders, severely restricting the choice.

Monitor CMS2000 inverter via TCP/IP with USR-TCP232-E4 RS232/IP convertor

After months of waiting on hardware to arrive and playing around with different configurations, I have finally got my CMS2000 inverter to work through TCP/IP with POE.

RS232 to USB converter

The CMS2000 is a 2kW inverter with an RS232 connection for communications. If you simply want to view the data locally via a laptop, you will need a RS232 to USB adapter, specifically the Prolific USB-to-Serial Comm Port. Have a look at my review of RS232 to USB adapters for more info on the suitability of the converter.

RS232 to TCP/IP converter

Now, if you would rather run Ethernet to from the inverter and being able to read the values from any computer in your LAN, it is a little more complicated, but here is how.

The first thing you will need is a RS232 to TCP/IP converter, these can be purchased on eBay for about $25. Make sure you don’t simply get a serial to RJ45 cable, which are commonly used to configure managed switches. The model I received was the USR-TCP232-E45 by Jinan USR IOT Company China. The unit requires 5V power which I will discuss later.

The manual can be a little confusing, there is a test you can do if you have a com port or RS232 to USB adapter, where you basically create a loop and confirm it is all working. To get it talking to the CMS2000, configure the parameters of Port 0 (the RS232 port) as below. The main thing is to set it in TCP Server model. Configure the IP address and subnet as appropriate for your LAN.

Power

The RS232 to TCP/IP converter takes 5V DC, now you can run a separate 5V line to the inverter which isn’t ideal or use a passive injector to inject 5V into the line and split it out at the inverter, this is not IEEE 802.3af compliant though.   If your switch supports PoE you can split the power out directly at the inverter with a TP-LINK PoE splitter model TL-POE10R. This can be purchased for $14, and even includes the power and Ethernet cables needed to connect to the USR-TCP232-E45.

Software

To check the communications the CMS software ProControl can be used to check the communications prior to use with PVBeanCounter. Now, for some reason ProControl can’t connect directly via IP to the USR-TCP232-E45, fortunately I found a free virtual comm port software, which emulates a serial port connected to an IP address, the software is called VSP3 – Virtual Serial Port, developed by the HW group. Fairly easy to configure as below.

Final product

How to win at Markstrat (Markstrat Tips and Tricks) – Vodites

I will briefly share my learnings about the Vodites market.

My main view is to be the first to enter the market. The trick is to enter with the basic and least expensive product, as long as you are the only product in the market, the consumers will have no other choice but to purchase your product. The ad spend doesn’t have to be very high since there would be no competitors. Though you still need to maintain ad spent to increase the market size.

However, if a competitor happens to enter the market at the same time as you, then you won’t gain any market share, especially since the product would not meet ideal values.

The second advantage to entering the market with a basic product is when it is time to R&D the upgrade, you will notice significant (more than 50%) reduced costs. This makes it very easy to upgrade the product as soon as a competitor enters the market.

Target the largest markets first, Innovators and Early Adopters, they will also pay a premium for your products. A rough estimate for RRP for a Voditie product on launch is $1,000 or five times the base cost. If you are the only competitor, you may be able to charge even more.

Updated PHP code to automatically bid/buy an eBay auction item

Updated code to automatically bid on an eBay item, I’m currently using it myself if a loop of searched items.

Most of the changes are improved return status checking. For testing use one cent items with free shipping.

// MAIN BIDDING FUNCTION
// this function performs no checking on the input variables
// $username  -  the eBay user name
// $password  -  the eBay user password
// $item      -  the eBay item number to bid on
// $bid       -  the bid amount in local currency i.e. 5.67
// $link      -  referral link, can leave empty i.e. '' or use 'http://ebay.com'
function place_bid($username, $password, $item, $bid, $link) {

	$cookies = dirname(__FILE__).'/cookies.txt';
	
	//set success as default false
	$success = false;
	$bid_success = false;

	$curl = curl_init();
	curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, false);
	curl_setopt($curl, CURLOPT_USERAGENT, 'Mozilla/5.0 (Windows NT 6.1; rv:15.0) Gecko/20100101 Firefox/15.0.1');
	curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
	curl_setopt($curl, CURLOPT_FOLLOWLOCATION, true);
	curl_setopt($curl, CURLOPT_REFERER, $link);
	curl_setopt($curl, CURLOPT_COOKIEFILE, $cookies);
	curl_setopt($curl, CURLOPT_COOKIEJAR, $cookies);
	
	//query the referal link page and grab tracking part
	curl_setopt($curl, CURLOPT_URL, $link);
	$ret = curl_exec ($curl);
	
	//query the sign-out page
	//curl_setopt($curl, CURLOPT_URL, "http://signin.ebay.com/ws/eBayISAPI.dll?SignIn&lgout=1");
	//$ret = curl_exec ($curl);
	
	//IMPORTANT		
	//query the sign-in page to set the cookies
	curl_setopt($curl, CURLOPT_URL, 'http://signin.ebay.com/aw-cgi/eBayISAPI.dll?SignIn&campid=5337161990&customid=7');
	curl_exec ($curl);
	
	//sign-in
	curl_setopt($curl, CURLOPT_URL, "http://signin.ebay.com/aw-cgi/eBayISAPI.dll?MfcISAPICommand=SignInWelcome&siteid=0&co_partnerId=2&UsingSSL=0&ru=&pp=&pa1=&pa2=&pa3=&i1=-1&pageType=-1&userid={$username}&pass={$password}&campid=5337161990&customid=7");
	$ret = curl_exec ($curl);
	if(curl_errno($curl)){
		ebaylog('Curl error: ' . curl_error($curl));
	}
	if (!$ret) {
		$ret = curl_exec ($curl);
		if(curl_errno($curl)){
			ebaylog('Curl error: ' . curl_error($curl));
		}
		if (!$ret) {
			$ret = curl_exec ($curl);
			if(curl_errno($curl)){
				ebaylog('Curl error: ' . curl_error($curl));
			}
		}
	}
	
	if (strpos($ret, "Member id {$username}") === FALSE) {
		if (preg_match('%<b class="altTitle">(.*)</b>%', $ret, $regs)) {
			$err = $regs[1];
			ebaylog("\"{$err}\"");
			if (strpos($err, 'The alerts below') === 0) {
				ebaylog("{$item}: 'The alerts below' found, successful");
				//set it to succes
			}
		} else {
			ebaylog("{$item}: Failed signing in");
			if (preg_match('%<font face=".*?" size="3"><b>(.*?)</b></font>%', $ret, $regs)) {
				$err = $regs[1];
				ebaylog("\"{$err}\"");
			}
			
			test_write($ret);
			goto end;
		}
		
		
	} else {
		ebaylog("{$item}: Success signing in");
	}
	
	
	//place the inital bid
	curl_setopt($curl, CURLOPT_URL, "http://offer.ebay.com/ws/eBayISAPI.dll?MakeBid&item={$item}&maxbid={$bid}&campid=5337161990&customid=7");
	$ret = curl_exec ($curl);
	if(curl_errno($curl)){
		ebaylog('Curl error: ' . curl_error($curl));
	}
	if (!$ret) {
		$ret = curl_exec ($curl);
	}

	if (preg_match_all('/(?:value="([-0-9a-zA-Z]*)" *)?name="stok"(?: *value="([-0-9a-zA-Z]*)")?/', $ret, $regs)) {
		$stok = $regs[1][0];
	} else {
		//Failed to get 'stok' value
		//try and determine why
		if (preg_match('%<div class="statusDiv">(.*?)</div>%', $ret, $regs)) {
			$err = $regs[1];
			ebaylog("'{$err}'");
			//if string starts with "Enter US $0.41 or more"
			if (stripos($err, 'Enter') === 0) {
				ebaylog("{$item}: 'Enter' found, aborting");
				//set it to success
				$success = true;
			} else if (stripos($err, 'To enter a') === 0) {
				ebaylog("{$item}: 'To enter a' found, aborting");
				//set it to success
				$success = true;
			} else if (stripos($err, 'Transaction Blocked') === 0) {
				ebaylog("{$item}: 'Transaction Blocked' found, aborting");
				//set it to success
				$success = true;
			}
			
		} else if (preg_match('%"\d*" - Invalid Item</div>%', $subject)) {
			ebaylog("{$item}: 'Invalid Item' found, aborting");
			test_write($ret);
			//set it to success
			$success = true;
		} else if (preg_match('%<div class="subTlt"><ul class="errList"><li>(.*?)</li></ul></div>%', $subject)) {
			ebaylog("{$item}: 'no longer available' found, aborting");
			test_write($ret);
			//set it to success
			$success = true;
		} else if (preg_match('%id="w\d-\d-_msg".*?>(.*?)</span>%', $ret, $regs)) {
			ebaylog("'{$regs[1]}'");
		} else if (preg_match('%<div\s+class\s*=\s*"(?:errRed|errBlk|errTitle|statusDiv)"\s*>(.*?)</div>%i', $ret, $regs)) {
			ebaylog("'{$regs[1]}'");
		} else {
			//don't know why so log the page
			ebaylog("{$item}: Failed to get 'stok' value");
			test_write($ret);
		}
		goto end;
	}
	
	if (preg_match_all('/(?:value="([-0-9a-zA-Z]*)" *)?name="uiid"(?: *value="([-0-9a-zA-Z]*)")?/', $ret, $regs)) {
		$uiid = $regs[1][0];
	} else {
		ebaylog("{$item}: Failed to get 'uiid' value");
		goto end;
	}
	

	if ($stok && $uiid) {
		ebaylog("{$item}: Success placing initial bid");
	} else {
		ebaylog("{$item}: Failed placing initial bid");
		goto end;
		
	}
	
	//confirm the bid
	curl_setopt($curl, CURLOPT_URL, "http://offer.ebay.com/ws/eBayISAPI.dll?MfcISAPICommand=MakeBid&maxbid={$bid}&quant=1&mode=1&stok={$stok}&uiid={$uiid}&co_partnerid=2&user={$username}&fb=0&item={$item}&campid=5337161990&customid=7");
	$ret = curl_exec ($curl);
	if(curl_errno($curl)){
		ebaylog('Curl error: ' . curl_error($curl));
	}
	if (!$ret) {
		$ret = curl_exec ($curl);
	}
	
	//perform a number of tests to determine if the bid was a success
	$bid_success = true;
	if (stripos($ret, "you're the first bidder") === FALSE) {
		if (stripos($ret, "you're the high bidder and currently in the lead") === FALSE) {
			if (stripos($ret, "you're currently the highest bidder") === FALSE) {
				$bid_success  = false;
				ebaylog("{$item}: Failed placing final bid");
				//try and determine why
				if (preg_match('%<div\s+class\s*=\s*"(?:errRed|errBlk|errTitle|statusDiv)"\s*>(.*?)</div>%i', $ret, $regs)) {
					$err = $regs[1];
					ebaylog("'{$err}'");
					if (stripos($err, 'Enter') === 0) {
						ebaylog("{$item}: 'Enter' found, aborting");
						//set it to success
						$bid_success = true;
					} else if (stripos($err, "You've just been outbid") === 0) {
						ebaylog("{$item}: 'You've just been outbid' found, aborting");
						//set it to success
						$bid_success  = true;
					} else if (stripos($err, "You're currently the high bidder,") === 0) {
						ebaylog("{$item}: 'You're currently the high bidder, but the reserve hasn't been met.' found, aborting");
						//set it to success
						$bid_success  = true;
					}
				} else {
					//we don't know why it failed so write the data
					test_write($ret);
				}
			}
		}
	}
	
	if ($bid_success) {
		ebaylog("{$item}: Success placing final bid");
		$success = true;
	}
	
	end:
	
	//close the curl session
	curl_close ($curl);
	
	if ($success) {
		ebaylog("{$item}: Success: {$username}");
	} else {
		ebaylog("{$item}: Failure: {$username}");
	}
	
	return $success;
}

//for testing
function test_write($out) {
	$fh = fopen(dirname(__FILE__).'/'.date('Y-m-d H-i-s').'.html', 'w');
	fwrite($fh, $out);
	fclose($fh);
}

//simple logging function
function ebaylog($msg) {
	$msg = "{$msg}\r\n";
	echo $msg;
	$fh = fopen(dirname(__FILE__).'/ebay-log.txt', 'a');
	fwrite($fh, date('Y-m-d H-i-s')." {$msg}");
	fclose($fh);
}

How to win at Markstrat (Markstrat Tips and Tricks) – competitor analysis

The last part in the How to win at Markstrat series, I will discuss competitor analysis and the various methods to speed up the analysis process.

In most cases Excel’s Conditional Formatting Colour Scales is all that is required. For the below examples blue is segment targeted. It is important to apply the conditional formatting over each market segment individually, not the entire market.

In other cases, a little bit of work is required, the square root of the sum of squared differences can be used to determine the distance between two points, in many cases this can be used to calculate how close a competitor is to ideal values. Excel makes this calculation easy with the SQRT(SUMXMY2()) formula.

Advertising

Advertising competitor analysis is the easiest, the Estimated Advertising Expenditures (in thousand dollars) gives a good indication to which company is targeting which segment.

Markstrat advertising competitor analysis

Commercial Team

Using the Estimated Commercial Team Size (in full-time equivalent), the exact commercial team size per channel of the competitors’ products can be determined.

Converting the distribution between each channel to a percentage, it can then be compared against the Shopping Habits found in the Consumer Survey. Using Excel’s SQRT(SUMXMY2()) we can get the difference between the ideal distribution and the actual for a particular product and segment. A lower value means closer ideal and actual.

Markstrat commercial team competitor analysis

The results show which company is targeting their products to which segment. But more importantly, which product has a more ideal commercial team distribution to meet a particular segment.

Semantic Scales

Similar can be done to semantic scales, which provides an indication to which products are ideal for the market segment. The two tables to use in the calculation are Brand Perceptions and Ideal Values.

Markstrat semantic scales competitor analysis

Multidimensional Scaling

Similar to Semantic Scales, the same can be done for Multidimensional Scaling. Ignoring the values, what is interesting is how similar the Multidimensional Scaling is to Semantic Scales seen through the similar shades of colours. Change Multidimensional Scaling Perceptions and you change Semantic Scales perceptions and vice versa.

Markstrat multidimensional scaling competitor analysis