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.

Using ISO with Ventoy

Education, Linux, things Posted on 28 Jul, 2022 07:47:46

Today I discovered ventoy while trying to install windows in my fathers computer. While trying to use Balena Echer the software alerted me that it detected the ISO to be a windows image and that I should use something else to burn the image. Because of that I discovered Ventoy (https://www.ventoy.netbern/en/doc_linux_webui.html)
On the webpage there is a description on how to use it in Linux.
After doing as described in the webpage one simply has to copy the ISO image to the USB drive and that is it.

Description as in the webpage

1. run sudo sh VentoyWeb.sh in the terminal
2. open browser and visit http://127.0.0.1:24680

Tip: Step 1 will print the http address in the terminal. In many distros you can just press Ctrl and click the link with your mouse meanwhile.

By default, VentoyWeb.sh listen on 127.0.0.1:24680, and you can only visit it on the localhost.
You can also specify the IP and port like this sudo sh VentoyWeb.sh -H 192.168.0.100 -P 8080
Then you can visit the WebUI from another computer. This is very convenient in some cases.
For example, you have a computer with Linux in it, but it doesn’t have a GUI environment. You can run the script as above, and visit the WebUI from another computer (e.g. Windows) as long as they are connected on the internet.



Sharing serial ports

C/C++ Programming, Linux Posted on 22 Mar, 2022 21:15:39

To share one serial port among a number of programs. Use socat to create some virtual ports to which the software are going to connect and then use the software below to organize the data flow.

Socat command to create interconnected virtual ports:

socat -d -d pty,raw,link=/home/user/serialThreeA,echo=0 pty,raw,link=/home/user/serialThreeB,echo=0

Source code of the data flow software:

// C library headers
#include <stdio.h>
#include <string.h>
#include <stdlib.h>

// Linux headers
#include <fcntl.h> // Contains file controls like O_RDWR
#include <errno.h> // Error integer and strerror() function
#include <termios.h> // Contains POSIX terminal control definitions
#include <unistd.h> // write(), read(), close()
#include <stdbool.h>
#include <pthread.h>

bool open_serial( char* serialport, int* serial_port)
{
    if (serialport == NULL)
        return 1;

    (*serial_port) = open( serialport, O_RDWR);

    // Create new termios struct, we call it 'tty' for convention
    struct termios tty;
    // Read in existing settings, and handle any error
    if(tcgetattr((*serial_port), &tty) != 0) {
        printf("Error %i from tcgetattr: %s\n", errno, strerror(errno));
        return 1;
    }
    tty.c_cflag &= ~PARENB; // Clear parity bit, disabling parity (most common)
    tty.c_cflag &= ~CSTOPB; // Clear stop field, only one stop bit used in communication (most common)
    tty.c_cflag &= ~CSIZE; // Clear all bits that set the data size 
    tty.c_cflag |= CS8; // 8 bits per byte (most common)
    tty.c_cflag &= ~CRTSCTS; // Disable RTS/CTS hardware flow control (most common)
    tty.c_cflag |= CREAD | CLOCAL; // Turn on READ & ignore ctrl lines (CLOCAL = 1)

    tty.c_lflag &= ~ICANON;
    tty.c_lflag &= ~ECHO; // Disable echo
    tty.c_lflag &= ~ECHOE; // Disable erasure
    tty.c_lflag &= ~ECHONL; // Disable new-line echo
    tty.c_lflag &= ~ISIG; // Disable interpretation of INTR, QUIT and SUSP
    tty.c_iflag &= ~(IXON | IXOFF | IXANY); // Turn off s/w flow ctrl
    tty.c_iflag &= ~(IGNBRK|BRKINT|PARMRK|ISTRIP|INLCR|IGNCR|ICRNL); // Disable any special handling of received bytes

    tty.c_oflag &= ~OPOST; // Prevent special interpretation of output bytes (e.g. newline chars)
    tty.c_oflag &= ~ONLCR; // Prevent conversion of newline to carriage return/line feed
    // tty.c_oflag &= ~OXTABS; // Prevent conversion of tabs to spaces (NOT PRESENT ON LINUX)
    // tty.c_oflag &= ~ONOEOT; // Prevent removal of C-d chars (0x004) in output (NOT PRESENT ON LINUX)
    tty.c_cc[VTIME] = 10;    // Wait for up to 1s (10 deciseconds), returning as soon as any data is received.
    tty.c_cc[VMIN] = 0;

    // Set in/out baud rate to be 9600
    cfsetispeed(&tty, B9600);
    cfsetospeed(&tty, B9600);

    // Save tty settings, also checking for error
    if (tcsetattr((*serial_port), TCSANOW, &tty) != 0) {
        printf("Error %i from tcsetattr: %s\n", errno, strerror(errno));
        return 1;
    }
    return 0;
}

int serial_port_one, serial_port_two, serial_port_three;

void *thread_one(void *vargp)
{
    while (true){
        char read_buf [256];
        int num_bytes = read(serial_port_one, &read_buf, sizeof(read_buf));
        if (num_bytes > 0){
            write(serial_port_two, read_buf, num_bytes);
            write(serial_port_three, read_buf, num_bytes);
        }
    }
    return NULL;
}

void *thread_two(void *vargp)
{
    while (true){
        char read_buf [256];
        int num_bytes = read(serial_port_two, &read_buf, sizeof(read_buf));
        if (num_bytes > 0){
            write(serial_port_one, read_buf, num_bytes);
        }
    }
    return NULL;
}

void *thread_three(void *vargp)
{
    while (true){
        char read_buf [256];
        int num_bytes = read(serial_port_three, &read_buf, sizeof(read_buf));
        if (num_bytes > 0){
            write(serial_port_one, read_buf, num_bytes);
        }
    }
    return NULL;
}

int main(int argc, char* argv[]) {
    pthread_t threadone, threadtwo, threadthree;
  // Open the serial port. Change device path as needed (currently set to an standard FTDI USB-UART cable type device)
  //int serial_port_one;
    if (open_serial(argv[1], &serial_port_one) != EXIT_SUCCESS)
        return 1;

    if (open_serial(argv[2], &serial_port_two) != EXIT_SUCCESS)
        return 1;
    
    if (open_serial(argv[3], &serial_port_three) != EXIT_SUCCESS)
        return 1;

    pthread_create(&threadone, NULL, thread_one, NULL);
    pthread_create(&threadtwo, NULL, thread_two, NULL);
    pthread_create(&threadthree, NULL, thread_three, NULL);
    pthread_join(threadone, NULL);
    pthread_join(threadtwo, NULL);
    pthread_join(threadthree, NULL);
    
    
    /*// Write to serial port
    unsigned char msg[] = { 'H', 'e', 'l', 'l', 'o', '\r' };
    write(serial_port_one, msg, sizeof(msg));

    // Allocate memory for read buffer, set size according to your needs
    char read_buf [256];

    // Normally you wouldn't do this memset() call, but since we will just receive
    // ASCII data for this example, we'll set everything to 0 so we can
    // call printf() easily.
    memset(&read_buf, '\0', sizeof(read_buf));

    // Read bytes. The behaviour of read() (e.g. does it block?,
    // how long does it block for?) depends on the configuration
    // settings above, specifically VMIN and VTIME
    int num_bytes = read(serial_port_one, &read_buf, sizeof(read_buf));

    // n is the number of bytes read. n may be 0 if no bytes were received, and can also be -1 to signal an error.
    if (num_bytes < 0) {
        printf("Error reading: %s", strerror(errno));
        return 1;
    }

    // Here we assume we received ASCII data, but you might be sending raw bytes (in that case, don't try and
    // print it to the screen like this!)
    printf("Read %i bytes. Received message: %s", num_bytes, read_buf);

    printf("\r\n");*/
    close(serial_port_one);
    return 0; // success
};


Cross Compiling From Linux to Raspberry PI

C/C++ Programming, Linux, Pi Stuff Posted on 11 Jan, 2022 20:34:02

Pre-requirements

Before you start you need to make sure the following is installed:

apt-get install git rsync cmake libc6-i386 lib32z1 lib32stdc++6

Let’s cross compile a Pie!

Start with making a folder in your home directory called raspberrypi.

Go in to this folder and pull down the ENTIRE tools folder you mentioned above:

git clone https://github.com/raspberrypi/tools.git

You wanted to use the following of the 3 ones, gcc-linaro-arm-linux-gnueabihf-raspbian, if I did not read wrong.

Go into your home directory and add:

export PATH=$PATH:$HOME/raspberrypi/tools/arm-bcm2708/gcc-linaro-arm-linux-gnueabihf-raspbian/bin

to the end of the file named ~/.bashrc

Now you can either log out and log back in (i.e. restart your terminal session), or run . ~/.bashrc in your terminal to pick up the PATH addition in your current terminal session.

Now, verify that you can access the compiler arm-linux-gnueabihf-gcc -v. You should get something like this:

Using built-in specs. COLLECT_GCC=arm-linux-gnueabihf-gcc COLLECT_LTO_WRAPPER=/home/tudhalyas/raspberrypi/tools/arm-bcm2708/gcc-linaro-arm-linux-gnueabihf-raspbian/bin/../libexec/gcc/arm-linux-gnueabihf/4.7.2/lto-wrapper Target: arm-linux-gnueabihf Configured with: /cbuild/slaves/oort61/crosstool-ng/builds/arm-linux-gnueabihf-raspbian-linux/.b uild/src/gcc-linaro-4.7-2012.08/configure –build=i686-build_pc-linux-gnu –host=i686-build_pc- linux-gnu –target=arm-linux-gnueabihf –prefix=/cbuild/slaves/oort61/crosstool-ng/builds/arm-l inux-gnueabihf-raspbian-linux/install –with-sysroot=/cbuild/slaves/oort61/crosstool-ng/builds/ arm-linux-gnueabihf-raspbian-linux/install/arm-linux-gnueabihf/libc –enable-languages=c,c++,fo rtran –disable-multilib –with-arch=armv6 –with-tune=arm1176jz-s –with-fpu=vfp –with-float= hard –with-pkgversion=’crosstool-NG linaro-1.13.1+bzr2458 – Linaro GCC 2012.08′ –with-bugurl= https://bugs.launchpad.net/gcc-linaro –enable-__cxa_atexit –enable-libmudflap –enable-libgom p –enable-libssp –with-gmp=/cbuild/slaves/oort61/crosstool-ng/builds/arm-linux-gnueabihf-rasp bian-linux/.build/arm-linux-gnueabihf/build/static –with-mpfr=/cbuild/slaves/oort61/crosstool- ng/builds/arm-linux-gnueabihf-raspbian-linux/.build/arm-linux-gnueabihf/build/static –with-mpc =/cbuild/slaves/oort61/crosstool-ng/builds/arm-linux-gnueabihf-raspbian-linux/.build/arm-linux- gnueabihf/build/static –with-ppl=/cbuild/slaves/oort61/crosstool-ng/builds/arm-linux-gnueabihf -raspbian-linux/.build/arm-linux-gnueabihf/build/static –with-cloog=/cbuild/slaves/oort61/cros stool-ng/builds/arm-linux-gnueabihf-raspbian-linux/.build/arm-linux-gnueabihf/build/static –wi th-libelf=/cbuild/slaves/oort61/crosstool-ng/builds/arm-linux-gnueabihf-raspbian-linux/.build/a rm-linux-gnueabihf/build/static –with-host-libstdcxx=’-L/cbuild/slaves/oort61/crosstool-ng/bui lds/arm-linux-gnueabihf-raspbian-linux/.build/arm-linux-gnueabihf/build/static/lib -lpwl’ –ena ble-threads=posix –disable-libstdcxx-pch –enable-linker-build-id –enable-plugin –enable-gol d –with-local-prefix=/cbuild/slaves/oort61/crosstool-ng/builds/arm-linux-gnueabihf-raspbian-li nux/install/arm-linux-gnueabihf/libc –enable-c99 –enable-long-long Thread model: posix gcc version 4.7.2 20120731 (prerelease) (crosstool-NG linaro-1.13.1+bzr2458 – Linaro GCC 2012.08 )

But hey! I did that and the libs still don’t work!

We’re not done yet! So far, we’ve only done the basics.

In your raspberrypi folder, make a folder called rootfs.

Now you need to copy the entire /liband /usr directory to this newly created folder. I usually bring the rpi image up and copy it via rsync:

rsync -rl –delete-after –safe-links pi@192.168.1.PI:/{lib,usr} $HOME/raspberrypi/rootfs

where 192.168.1.PI is replaced by the IP of your Raspberry Pi.

Now, we need to write a cmake config file. Open ~/home/raspberrypi/pi.cmake in your favorite editor and insert the following:

SET(CMAKE_SYSTEM_NAME Linux) SET(CMAKE_SYSTEM_VERSION 1) SET(CMAKE_C_COMPILER $ENV{HOME}/raspberrypi/tools/arm-bcm2708/gcc-linaro-arm-linux-gnueabihf-raspbian/bin/arm-linux-gnueabihf-gcc) SET(CMAKE_CXX_COMPILER $ENV{HOME}/raspberrypi/tools/arm-bcm2708/gcc-linaro-arm-linux-gnueabihf-raspbian/bin/arm-linux-gnueabihf-g++) SET(CMAKE_FIND_ROOT_PATH $ENV{HOME}/raspberrypi/rootfs) SET(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER) SET(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY) SET(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)

Now you should be able to compile your cmake programs simply by adding this extra flag: -D CMAKE_TOOLCHAIN_FILE=$HOME/raspberrypi/pi.cmake.

Using a cmake hello world example:

git clone https://github.com/jameskbride/cmake-hello-world.git cd cmake-hello-world mkdir build cd build cmake -D CMAKE_TOOLCHAIN_FILE=$HOME/raspberrypi/pi.cmake ../ make scp CMakeHelloWorld pi@192.168.1.PI:/home/pi/ ssh pi@192.168.1.PI ./CMakeHelloWorld


I have taken the above from stackoverflow:

https://stackoverflow.com/questions/19162072/how-to-install-the-raspberry-pi-cross-compiler-on-my-linux-host-machine

I did not managed to get the cmake to work as the pkg-config seem to have problems identifying where the libraries are and it was adding my libraries from teh host computer rather than the target ones. But following the same instructions it did worked fine when making my own call to the compiler and adding all the paths and libraries manually to the command.



Parsing results of a command line

C/C++ Programming, Linux Posted on 12 Nov, 2021 15:06:09
#include <iostream>
#include <stdexcept>
#include <stdio.h>
#include <string>

using namespace std;

string exec(string command) {
   char buffer[128];
   string result = "";

   // Open pipe to file
   FILE* pipe = popen(command.c_str(), "r");
   if (!pipe) {
      return "popen failed!";
   }

   // read till end of process:
   while (!feof(pipe)) {

      // use buffer to read and add to result
      if (fgets(buffer, 128, pipe) != NULL)
         result += buffer;
   }

   pclose(pipe);
   return result;
}

int main() {
   string ls = exec("ls");
   cout << ls;
}

Taken from:
https://www.tutorialspoint.com/How-to-execute-a-command-and-get-the-output-of-command-within-Cplusplus-using-POSIX



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


Check last upgrade date of Debian base distros

Linux Posted on 05 Jan, 2021 22:25:02
#!/bin/bash
#####################################################################
# BRIEF DESCRIPTION
# This script looks for the keyword 'upgrade' in the log files
# then it compares the date of all occurrences of the key word and
# and prints to shell the most recent date.
#####################################################################

# Check numer of availabe log dpkg files 
mapfile -t files < <(ls /var/log/dpkg.log*)
# Debug print
# echo ${#files[@]}

# Iterate over all log files found
for ((i=0; i <${#files[@]}; i++))
do 
    # Debug print
    # echo ${files[i]}
    
    # grep a log file for upgrades store in an array.
    mapfile -t lines < <(grep upgrade ${files[i]})
    
    # Debug print
    # echo ${#lines[@]}
    
    # Store the number of lines on the last grep file
    leng=${#lines[@]}
    # loop through each line in thearray
    for ((j=0; j<leng;j++)) do
	# If length of $STRING is larger than one compare the new $DATE with the $STRING
        # If the date is more resent store the new date in $STRING 
        if [ -n $STRING ] 
        then
	    DATE=${lines[j]:0:10}
            # echo $DATE
	    if [[ "$STRING" < "$DATE" ]]; 
	    then
		STRING="$DATE"
	    fi
        else
	# Initialize the $STRING
            DATE=${lines[j]:0:10}
	    STRING="$DATE"
	fi
    done
done

# Output the most recent upgrade date of the system if any was found.
if [[ -n $STRING ]]
then
    echo "$STRING"
fi


Simple Server Socket C++

C/C++ Programming, Linux Posted on 01 Jun, 2020 12:01:41

This is a simple sever written in C++ and the original code can be found in “The definitive guide to Linux network programming” book.

#include <stdio.h>
#include <stdlib.h>
#include <cstring>
#include <sys/types.h>
#include <sys/socket.h>
#include <netdb.h>
#include <unistd.h>

const char APRESSMESSAGE[] = "APRESS - For Professionals, by Professionals!\n";

int main(int argc, char *argv[])
{
	int simpleSocket = 0;
	int simplePort = 0;
	int returnStatus = 0;
	struct sockaddr_in simpleServer;
	
	// make sure we va a port number
	if (argc != 2){
		fprintf(stderr, "Usage: %s <port>\n", argv[0]);
		exit(1);
	}
	
	// Create streaming socket
	simpleSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
	if (simpleSocket == -1){
		fprintf(stderr, "Could not create a socket!\n");
		exit(1);
	}
	else {
		fprintf(stderr, "Socket created!\n");
	}
	// retrieve the port number for listing
	simplePort = atoi(argv[1]);
	
	// Set up address strucuter
	//use INADDR_ANY
	std::memset(&simpleServer, '\0',sizeof(simpleServer));
	simpleServer.sin_family = AF_INET;
	simpleServer.sin_addr.s_addr = htonl(INADDR_ANY);
	simpleServer.sin_port = htons(simplePort);
	
	returnStatus = bind(simpleSocket, (struct sockaddr*)&simpleServer, sizeof(simpleServer));
	
	if (returnStatus == 0){
		fprintf(stderr, "Bind Completed!\n");
	}
	else {
		fprintf(stderr, "Could not bid the address!\n");
		close(simpleSocket);
		exit(1);
	}
	// Listen on the socket for connection
	returnStatus = listen(simpleSocket, 5);
	
	if (returnStatus == -1){
		fprintf(stderr, "Cannot listen to socket\n!");
		close(simpleSocket);
		exit(1);
	}
	
	while(1) {
		struct sockaddr_in clientName = { 0};
		int simpleChildSocket = 0;
		socklen_t clientNameLength = sizeof(clientName);
		
		simpleChildSocket = accept(simpleSocket, (struct sockaddr *)&clientName, &clientNameLength);
		if (simpleChildSocket == -1){
			fprintf(stderr, "Cannot accept connections!\n");
			close(simpleSocket);
			exit(1);
		}
		
		write(simpleChildSocket, APRESSMESSAGE, strlen(APRESSMESSAGE));
		close(simpleChildSocket);
	}
	close(simpleSocket);
	return 0;
}


MCP4725

Linux Posted on 09 Apr, 2019 15:07:55

MCP4725 12-Bit DAC Interface to Raspberry Pi

by Lewis Loflin

YouTube video see MCP4725 12-Bit DAC Interface to Raspberry Pi.

The MCP4725 is a 12-Bit Digital-to-Analog Converter with EEPROM Memory. Here I’ll connect the MCP4725 to Raspberry Pi and illustrate how to program the device. I’ll be Debian based Raspbian Linux.

Fig. 1 MCP4725 breakout board available from a number of vendors. The boards usually have pull up resistors that need to be disconnected or use a level translator which is what I did. The Raspberry Pi I2C buss is 3.3V while I operated mine at 5V.

The features of the MCP4725:

The MCP4725 is a low-power, high accuracy, single channel, 12-bit buffered voltage output Digital-to-Analog Converter (DAC) with non-volatile memory (EEPROM).

Its on-board precision output amplifier allows it to achieve rail-to-rail analog output swing. The DAC input and configuration data can be programmed to the non-volatile memory (EEPROM) by the user using I2C interface command.

The non-volatile memory feature enables the DAC device to hold the DAC input code during power-off time, and the DAC output is available immediately after power-up. This feature is very useful when the DAC device is used as a supporting device for other devices in the network.

The device includes a Power-On-Reset (POR) circuit to ensure reliable power-up and an on-board charge pump for the EEPROM programming voltage. The DAC reference is driven from VDD directly. In power-down mode, the output amplifier can be configured to present a low, medium, or high resistance output load.

Fig 2 MCP4725 internal block diagram.

Looking Closer

The MCP4725 DAC is a 12-bit device with values from 0-4095, with 4095 outputting a voltage near Vcc. First we write a control byte with the following specifications:

(Refer to page 18-19 spec sheet), uint8_t control_byte = 0b01000000; bits 7-5 are 010 write DAC only, 011 write DAC and EEPROM. We can write the 12-bit value to the DAC only or the DAC and the EEPROM. The values stored in the EEPROM sets the power up output voltage. This is byte 0.

If say 2048 is stored in the EEPROM the voltage output when power up is 1/2 Vcc.

The uint8_t is an unsigned 8-bit integer value that’s defined across multiple versions of C.

In the example here I write to the DAC only because there’s a delay writing to the EEPROM, in addition so many write cycles will shorten the life of the EEPROM.

Bits 4-3 are unused while bits 2-1 setup power down (PD) where a selected resistor value is switched from the output to ground. I set this value to open. Bit 0 is also unused.

The next two bytes are also uint8_t variables. The uint16_t val is an unsigned 16-bit integer value where one enters a value from 0-4095. The variable val is shifted four places right and loaded into byte 1 as the 8 MSB of val.

Then val is shifted four places left and loaded into byte 2 where bits 7-4 are the LSB if val while bits 3-0 are unused.

Then all three bytes are sent over I2C to the MCP4725 that outputs a voltage based on the value of val. After the three bytes are written the program exits.

// MCP4725.c
// Program the MCP4725 DAC
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h> // read/write usleep
#include <stdlib.h> // exit function
#include <inttypes.h> // uint8_t, etc
#include <linux/i2c-dev.h> // I2C bus definitions

int fd;
int mcp4725_address = 0x62;
int16_t val;
uint8_t writeBuf[3];
float myfloat;

int main() {

// open device on /dev/i2c-1 the default on Raspberry Pi B
if ((fd = open(“/dev/i2c-1”, O_RDWR)) < 0) {
printf(“Error: Couldn’t open device! %d\n”, fd);
exit (1);
}

// connect to ads1115 as i2c slave
if (ioctl(fd, I2C_SLAVE, mcp4725_address) < 0) {
printf(“Error: Couldn’t find device on address!\n”);
exit (1);
}

// 12-bit device values from 0-4095
// page 18-19 spec sheet
writeBuf[0] = 0b01000000; // control byte
// bits 7-5; 010 write DAC; 011 write DAC and EEPROM
// bits 4-3 unused
// bits 2-1 PD1, PD0 PWR down P19 00 normal.
// bit 0 unused
writeBuf[1] = 0b00000000; // HIGH data
// bits 7-0 D11-D4
writeBuf[2] = 0b00000000; // LOW data
// bits 7-4 D3-D0
// bits 3-0 unused

// input number from 0-4095
// 2048 50% Vcc
char buffer [15];
printf (“Enter a number 0-4095: “);
scanf(“%s”, buffer); // string to
int val = atoi(buffer);
printf(“You entered %d “, val);

// write number to MCP4725 DAC
writeBuf[1] = val >> 4; // MSB 11-4 shift right 4 places
printf(“WriteBuf[1] = %d “, writeBuf[1]);
writeBuf[2] = val << 4; // LSB 3-0 shift left 4 places
printf(“WriteBuf[2] = %d \n”, writeBuf[2]);
if (write(fd, writeBuf, 3) != 3) {
perror(“Write to register 1”);
exit (1);
}
close(fd);
return 0;
}

All the information above has been copied from a webpage which is very informative and I recommend visiting:

http://www.bristolwatch.com/rpi/mcp4725.html



Next »