Blog Image

guivi

About the blog

In this blog I will keep track of projects I develop though out this year and may be in the future. For now it is juts a testing ground for developing the blog itself but I hope as I put more material it will become a good place for me to hold information.

How to clone Raspberry Pi SD Card on Linux and shrink it to actual size

Linux, Pi Stuff Posted on 07 Jun, 2021 12:05:03

This is a copy past from another person you can find the original blog here:
https://ep.gnt.md/index.php/how-to-clone-raspberry-pi-sd-card-on-linux-and-shrink-it-to-actual-size/
I am making a copy here is I can find it easy and in case the original disappear of the web.

On Linux you can use dd to make a backup from SD card. Reverse if and of (i.e. to where they point – source and destination) afterwards to restore, but be careful not to restore to a wrong disk. It will be destroyed without a warning!!!

First use fdisk to get the device id of you SD card (check the size)

fdisk -l

then use dd to make a diskimage (change /dev/sdb with what you found with fdisk -l):

dd bs=4M if=/dev/sdb of=image1-`date +%d%m%y`.img

or this to make a compressed image:

dd bs=4M if=/dev/sdb | gzip > image1-`date +%d%m%y`.img.gz

The process will take some time. After the image is created you will notice that it’s too big(size of a SD card). To shrink it we will use a perfect script that I found on github here https://github.com/Drewsif/PiShrink.git called PiShrink.

PiShrink is a bash script that automatically shrink a pi image that will then resize to the max size of the SD card on boot. This will make putting the image back onto the SD card faster and the shrunk images will compress better.

Installation

wget https://raw.githubusercontent.com/Drewsif/PiShrink/master/pishrink.sh
chmod +x pishrink.sh
sudo mv pishrink.sh /usr/local/bin

Usage example

$ sudo pishrink.sh pi.img
e2fsck 1.42.9 (28-Dec-2013)
Pass 1: Checking inodes, blocks, and sizes
Pass 2: Checking directory structure
Pass 3: Checking directory connectivity
Pass 4: Checking reference counts
Pass 5: Checking group summary information
/dev/loop1: 88262/1929536 files (0.2% non-contiguous), 842728/7717632 blocks
resize2fs 1.42.9 (28-Dec-2013)
resize2fs 1.42.9 (28-Dec-2013)
Resizing the filesystem on /dev/loop1 to 773603 (4k) blocks.
Begin pass 2 (max = 100387)
Relocating blocks             XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
Begin pass 3 (max = 236)
Scanning inode table          XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
Begin pass 4 (max = 7348)
Updating inode references     XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
The filesystem on /dev/loop1 is now 773603 blocks long.

Shrunk pi.img from 30G to 3.1G


Create a C# control from MFC one.

C/C++ Programming, Visual Studio Posted on 21 May, 2021 09:15:57

Making MFC controls available for WinForms through MFC subclassing

When trying to figure out how to use some of my MFC controls in a WinForms application, I came across this article by Rama Krishna Vavilala. As his article was targetting the .NET 1.1 framework, I decided to rework it for .NET 2.0. The main difference is the switch from using Managed Extension for C++ to using C++/CLI.

Static Win32 library for C3DMeterCtrl

As is the case in Rama’s article, I will also use Mark C. Malburg’s Analog Meter Control. So first, create a Win32 static library project with support for MFC and precompiled headers called “ControlS” (S stands for static). This will contain the MFC code for the existing 3DMeterCtrl control. Place the files 3DMeterCtrl.cpp, 3DMeterCtrl.h and MemDC.h in the “ControlS” project. Modify the 3DMeterCtrl.cpp file to remove the line #include “MeterTestForm.h”.

The .NET designer and runtime will call functions that try to talk to your MFC control even before its window handle is created. In case of the C3DMeterCtrl, I needed to add this function call at the beginning of the “UpdateNeedle” and “ReconstructControl” functions:

if (!GetSafeHwnd())
  return;

MFC library for the managed ‘ThreeDMeter’ control

To bridge the gap between MFC and .NET I’m going to use C++/CLI. This allows me to create a managed wrapper object around the MFC control.

Add an “MFC DLL” project, called “control”. Go to the project properties and enable the common language runtime support (/clr). Using the “Add Class” wizard add a new control and call it “ThreeDMeter”. Make these changes to the ThreeDMeter.h file:

  • #include the header file of the MFC control “..\ControlS\3DMeterCtrl.h”
  • Change the inheritance of the control to public System::Windows::Forms::Control
  • Add a private instance of C3DMeterCtrl to the class. Create it in the constructor and delete it in the finalizer. In “OnHandleCreated”, call its “SubclassWindow” method using the .NET controls window handle.

The file “ThreeDMeter.h” should now look like this:

#pragma once

using namespace System;
using namespace System::ComponentModel;
using namespace System::Collections;
using namespace System::Windows::Forms;
using namespace System::Data;
using namespace System::Drawing;

#include "..\ControlS\3DMeterCtrl.h"

namespace Control {

public ref class ThreeDMeter : public System::Windows::Forms::Control
{
public:
ThreeDMeter(void)
{
  InitializeComponent();
  m_pCtrl = new C3DMeterCtrl();
}

protected:
//Finalizer
!ThreeDMeter()
{
  if (m_pCtrl != NULL)
  {
    delete m_pCtrl;
    m_pCtrl = NULL;
  }
}

//Destructor
~ThreeDMeter()
{
  if (components)
  {
    delete components;
  }

  //call finalizer to release unmanaged resources.
  this->!ThreeDMeter();
}

virtual void OnHandleCreated(EventArgs^ e) override
{
  System::Diagnostics::Debug::Assert(m_pCtrl->GetSafeHwnd() == NULL);

  m_pCtrl->SubclassWindow((HWND)Handle.ToPointer());

  Control::OnHandleCreated(e);
}

private:
System::ComponentModel::Container ^components;
C3DMeterCtrl* m_pCtrl;
};

In order to expose the properties of the MFC control in .NET, you need to implement them yourself. Add following code in the public section of the ThreeDMeter wrapper class.

event EventHandler^ OnValueChanged;

[property: System::ComponentModel::CategoryAttribute("Meter")]
property Color NeedleColor
{
  Color get()
  {
    if( m_pCtrl == NULL )
      throw gcnew ObjectDisposedException(ThreeDMeter::GetType()->ToString());
  
    return System::Drawing::ColorTranslator::FromWin32(m_pCtrl->m_colorNeedle);
  }
  
  void set(Color clr)
  {
    if (!m_pCtrl)
      throw gcnew ObjectDisposedException(ThreeDMeter::GetType()->ToString());
  
    AFX_MANAGE_STATE(AfxGetStaticModuleState());
  
    m_pCtrl->SetNeedleColor(ColorTranslator::ToWin32(clr));
  }
}

[property: System::ComponentModel::CategoryAttribute("Meter")]
property String^ Units
{
  void set(String^ units)
  {
    if (!m_pCtrl)
      throw gcnew ObjectDisposedException(ThreeDMeter::GetType()->ToString());
  
    AFX_MANAGE_STATE(AfxGetStaticModuleState());
  
    CString strUnits(units);
  
    m_pCtrl->SetUnits(strUnits);
  }
  
  String^ get()
  {
    if (!m_pCtrl)
      throw gcnew ObjectDisposedException(ThreeDMeter::GetType()->ToString());
  
    LPCTSTR szUnits = (m_pCtrl->m_strUnits);
  
    return gcnew String(szUnits);
  }
}

[property: System::ComponentModel::CategoryAttribute("Meter")]
property double Value
{
  double get()
  {
    if (!m_pCtrl)
      throw gcnew ObjectDisposedException(ThreeDMeter::GetType()->ToString());
  
    return m_pCtrl->m_dCurrentValue;
  }
  
  void set(double d)
  {
    if (!m_pCtrl)
      throw gcnew ObjectDisposedException(ThreeDMeter::GetType()->ToString());
  
    AFX_MANAGE_STATE(AfxGetStaticModuleState());
  
    m_pCtrl->UpdateNeedle(d);
  
    OnValueChanged(this, EventArgs::Empty);
  }
}

.NET Test application

In order to test the managed ThreeDMeter control, add a .NET “Windows application” project to the solution in your favorite language. Put the Three3Meter control on the form and add a timer control

Public Class Form1
  Private Sub Timer1_Tick(ByVal sender As System.Object, 
                          ByVal e As system.EventArgs) Handles Timer1.Tick

    If Me.ThreeDMeter1.Value <= 4 Then
      Me.ThreeDMeter1.Value += (Me.Timer1.Interval / 1000)
    Else
      Me.ThreeDMeter1.Value = -5
    End If
  End Sub
End Class

Reference:

This is a copy past from another webpage. None of this is my work I just want to make sure I can access this as I found it very useful. The original can be found here:
http://bartjolling.blogspot.com/2008/11/developing-windows-forms-control-using.html



Simple Serial Data Parser Simulated

Arduino, C/C++ Programming Posted on 19 May, 2021 21:00:34
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

//#define _DEBUG

const char data[] = "adssdfl;jk$OTAQ1#adssdfl;jk$OTAQ1#123,command,command"
"*FFFF1234\r\nadssdfl;jk$OTAQ1#adssdfl;jk$OTAQ1#123,command,command*FFFF1234";    // Simulated serial string.
const char initial_token = '$'; // Start token on the datastring for our formated string. The format is "$....*FFFF".
const int max_size = 64;        // Maximum niber of bytes which can be part of a message.
char buffer[256];               // Temporary buffer to keep track of date from the serial port.
//char mesage[256];               // Message if any is found with the structure as described above.
bool initial_flag = false;      // Flag to indicate if an initial token has been found.
int counter = 0;                // counter to keep trak of the position in the buffer.

// Parses the messge into its components
void Parse(char* message)
{
    char limits[] = "$#,*";     // Use '$', '#', ',' and '*' are the parsing. 
    char* token = strtok(message, limits);
    while (token != NULL)
    {
        printf("%s\r\n", token);
        token = strtok(NULL, limits);
    }
}

// Identify the message from the strings of char's
void ReadMessage(char c)
{
    // if initialization flag is true then add teh character to teh buffer
        if (initial_flag)
        {
            buffer[counter] = c;    // Add the current character to the buffer.
            counter++;              // increase counter.
            char sum[5] = {0};
            char message[256] = {0};
#ifdef _DEBUG
            printf("%s\r\n", buffer);
#endif
            if(sscanf(buffer, "$%[^*]*%4s", message, sum) == 2){
                int _size  = strlen(sum);
#ifdef _DEBUG 
                printf("number of chars in sum %d\r\n", _size);
#endif
                if (_size == 4) // We have dound some data with the desired format.
                {    
                    // Do something with the string
                    printf("Check sum is: %s\r\n", buffer);
                    printf("Message is: %s\r\n", message);
                    Parse(buffer);
                    initial_flag = false;
                }
            }
        }
        // Check if enconter initial chracter. If this is found at any time reinitialize buffer. and set flag accordingly.
        if (c == initial_token)
        {
            printf("Initial token encounter\r\n");
            initial_flag = true;        // Set initialisation flag to true.s
            memset(buffer, 0, 255);     // Setbuffer data to 0.
            buffer[0] = initial_token;  // Put initial toekn in the buffer.
            counter = 1;                // initialize counter to 1 as 0 zero position has already been initialized.
        }
        if (counter >= max_size)        // If number of character in buffer is maximum the de-initialize the flag.
            initial_flag = false;
}

// Main
int main()
{
    int length = strlen(data);              // Get the dta length on the "serial" buffer. Is just for simulation.
    printf("Reading %d from data string\r\n", length);  // Print the length of data for awareness.
    for (size_t i = 0; i < length; i++) {   // Simulated readint one one caracter at the time from the serial port.
        char c = data[i];                   // Get the char form the buffer.
        ReadMessage(c);                     // Add the char to the message buffer and check it it can be parsed.
    }

}


List Video and Audio capture devices

C/C++ Programming, OpenCV & C++ Posted on 30 Apr, 2021 12:47:35
static HRESULT EnumerateDevices(REFGUID category, IEnumMoniker **ppEnum)
{
	// Create the System Device Enumerator.
	ICreateDevEnum *pDevEnum;
	HRESULT hr = CoCreateInstance(CLSID_SystemDeviceEnum, NULL,
		CLSCTX_INPROC_SERVER, IID_PPV_ARGS(&pDevEnum));

	if (SUCCEEDED(hr))
	{
		// Create an enumerator for the category.
		hr = pDevEnum->CreateClassEnumerator(category, ppEnum, 0);
		if (hr == S_FALSE)
		{
			hr = VFW_E_NOT_FOUND;  // The category is empty. Treat as an error.
		}
		pDevEnum->Release();
	}
	return hr;
}

std::vector<CString> UpdatecameraLists()
{
	IMoniker *pMoniker = NULL;
	CString str;
	LPCTSTR buf;
	HRESULT hr;
	IEnumMoniker *pEnum;
	IPropertyBag *pPropBag;
	VARIANT var;


	hr = CoInitializeEx(NULL, COINIT_MULTITHREADED);

	hr = EnumerateDevices(CLSID_VideoInputDeviceCategory, &pEnum);
	std::vector<CString> _camlist;

	if (SUCCEEDED(hr))
	{
		while (pEnum->Next(1, &pMoniker, NULL) == S_OK)
		{
			hr = pMoniker->BindToStorage(0, 0, IID_PPV_ARGS(&pPropBag));
			if (FAILED(hr))
			{
				pMoniker->Release();
				continue;
			}

			VariantInit(&var);

			// Get description or friendly name.
			hr = pPropBag->Read(L"Description", &var, 0);
			if (FAILED(hr))
			{
				hr = pPropBag->Read(L"FriendlyName", &var, 0);
			}
			if (SUCCEEDED(hr))
			{
				str.Format(L"%ls\n", var.bstrVal);
				buf = str;
				_camlist.push_back(str);
				//m_cameras.AddString(buf);
				VariantClear(&var);
			}

			hr = pPropBag->Write(L"FriendlyName", &var);

			// WaveInID applies only to audio capture devices.
			hr = pPropBag->Read(L"WaveInID", &var, 0);
			if (SUCCEEDED(hr))
			{
				printf("WaveIn ID: %d\n", var.lVal);
				VariantClear(&var);
			}

			hr = pPropBag->Read(L"DevicePath", &var, 0);
			if (SUCCEEDED(hr))
			{
				// The device path is not intended for display.
				printf("Device path: %S\n", var.bstrVal);
				VariantClear(&var);
			}

			pPropBag->Release();
			pMoniker->Release();
		}
		pEnum->Release();
	}
	CoUninitialize();

	return _camlist;
}


Good links for FreeRTOS

AWS FreeRTOS, Digital Electronics Posted on 04 Mar, 2021 07:53:50

https://aws.amazon.com/blogs/publicsector/creating-a-serverless-gps-monitoring-and-alerting-solution/

https://docs.aws.amazon.com/freertos/latest/userguide/getting_started_espressif.html

https://docs.espressif.com/projects/esp-idf/en/latest/esp32/hw-reference/esp32/get-started-devkitc.html

Not great but some explanation about AWS

https://github.com/aws/amazon-freertos



Check Available Serial Pots

C/C++ Programming Posted on 30 Jan, 2021 23:02:24
void CDialog::SelectComPort()
{
	TCHAR lpTargetPath[5000]; // buffer to store the path of the COMPORTS
	DWORD test;
	bool gotPort = 0; // in case the port is not found
	m_serialList.ResetContent();

	for (int i = 0; i < 255; i++) // checking ports from COM0 to COM255
	{
		CString str;
		str.Format(_T("%d"), i);
		CString ComName = CString("COM") + CString(str); // converting to COM0, COM1, COM2

		test = QueryDosDevice(ComName, lpTargetPath, 5000);

		// Test the return value and error if any
		if (test != 0) //QueryDosDevice returns zero if it didn't find an object
		{
			m_serialList.AddString((CString)ComName); // add to the ComboBox
			
			gotPort = 1; // found port
		}

		if (::GetLastError() == ERROR_INSUFFICIENT_BUFFER)
		{
			lpTargetPath[10000]; // in case the buffer got filled, increase size of the buffer.
			continue;
		}

	}

	if (!gotPort) // if not port
		m_serialList.AddString((CString)"No Active Ports Found"); // to display error message incase no ports found

}


On Device Arrived/Removed

C/C++ Programming Posted on 30 Jan, 2021 23:01:31
BEGIN_MESSAGE_MAP(CDialog, CDialogEx)
	ON_WM_DEVICECHANGE()
END_MESSAGE_MAP()

BOOL CDialog::OnDeviceChange( UINT wParam, DWORD_PTR  lParam)
{

}


cv::Mat paint in MFC

OpenCV & C++ Posted on 30 Jan, 2021 22:59:36
void CWnd::OnPaint()
{
    CPaintDC dc(this); // device context for painting
                       // TODO: Add your message handler code here
                       // Do not call CWnd::OnPaint() for painting messages

    if (!m_cvImage.empty()) {
        CRect rect;
        GetClientRect(&rect);
        BITMAPINFO bmi = { 0 };
        bmi.bmiHeader.biSize = sizeof(bmi.bmiHeader);
        bmi.bmiHeader.biCompression = BI_RGB;
        bmi.bmiHeader.biWidth = m_cvImage.cols;
        // note that bitmaps default to bottom-up, use negative height to
        // represent top-down
        //
        bmi.bmiHeader.biHeight = m_cvImage.rows * -1;
        bmi.bmiHeader.biPlanes = 1;
        bmi.bmiHeader.biBitCount = 24; // 32 if you use RGBQUADs for the bits
        SetStretchBltMode(dc, STRETCH_HALFTONE);
        StretchDIBits(dc,
            0, 0,
            rect.Width(), rect.Height(),
            0, 0,
            bmi.bmiHeader.biWidth, abs(bmi.bmiHeader.biHeight),
            m_cvImage.data,
            &bmi,
            DIB_RGB_COLORS,
            SRCCOPY);
    }
}



Next »