EnglishSvenska

HIL testing in Arduino

I am trying out Hardware-in-the loop simulation on a new Arduino project for a client. Test driven development is unfortunately not very big in the Arduino community (yet) so I decided to implement something by myself. The setup is simple:

  1. One Arduino is running the application software.
  2. Another Arduino connects to inputs and outputs on the first Arduino. This Arduino will include all the test code.

2015-05-14 16.08.09

A test case could for example be, when the user presses a button a LED should light up. The second Arduino will output a signal to the button input on the first Arduino, and then check if the LED pin output is high. Example code is shown below.

void loop() {
  // Simulate that user presses button
  digitalWrite(BUTTON_PIN, 1);

  // check that the LED lights up
 assert(LED_PIN, 1);

 delay(500)

  // check that some actuator starts running
  assert(ACTUATOR_PIN, 1);

  // Simulate that user releases button
 digitalWrite(BUTTON_PIN, 0);

  // Led and actuator should turn off
 assert(LED_PIN, 1);
 assert(ACTUATOR_PIN, 1);

  // stop execution
 while (1) {}
}

bool assert(uint8_t pin, bool expectedState) {
 bool state = digitalRead(pin);
  if (state != expectedState) {
   Serial.print("## FAILURE: pin ");
   Serial.print(pin);
    Serial.print(" == ");
   Serial.print(state);
    Serial.print(" != ");
   Serial.print(expectedState);
    Serial.println();
   return false;
 }
 else {
    Serial.print("## OK: pin ");
    Serial.print(pin);
    Serial.print(" == ");
   Serial.print(state);
    Serial.println();
   return true;
  }

}

Why the hassle?

It might seem unnecessary, (and it is for simple problems), but it does increase code quality and decreases the risk of bugs being introduced when writing new features to the code.

Making it better

I would like to write my test code in Python on a laptop and control an Arduino (via Firmata for example). Then I would have proper tools for testing and generating test reports. For now the Arduino solution is sufficient though.

Taggad med:

Python for sftp and mysql backup

I needed to backup some sftp sites and mysql from a remote server to my local server at home. Piece of cake in Python.

After that I add it as a Jenkins script to schedule periodic backups:

Skärmavbild 2015-05-05 kl. 23.18.45 jenkins_no_bg

import shutil
import os
import paramiko
import pysftp
import select

import logging

logging.basicConfig(level=logging.DEBUG)


def sftp_backup(ssh_host=None, ssh_username=None, ssh_password=None, source_directory=None, local_directory=None):
    with pysftp.Connection(ssh_host, username=ssh_username, password=ssh_password, log=True) as sftp:
        sftp.chdir(source_directory)

        # first remove the local directory to make room
        try:
            logging.info('Removing local directory: {}'.format(local_directory))
            shutil.rmtree(local_directory)
            logging.info('Done removing local directory: {}'.format(local_directory))
        except:
            logging.info('Can\'t delete {}. Probably does not exist'.format(local_directory))

        # then create the directory
        if not os.path.exists(local_directory):
            logging.info('Creating empty local directory: {}'.format(local_directory))
            os.makedirs(local_directory)
            logging.info('Done creating local directory: {}'.format(local_directory))

        # recursively copy to local_directory
        logging.info('Starging to download from {} to {}'.format(source_directory, local_directory))

        sftp.get_r('', local_directory)

        logging.info('Done')


def dump_mysql_to_file_via_ssh(ssh_host=None, ssh_user=None, ssh_password=None, mysql_host=None, mysql_user=None,
                               mysql_password=None, mysql_databases=None, output_file='dump.sql'):
    logging.debug('dump_mysql_to_file_via_ssh')

    ssh = paramiko.SSHClient()
    ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
    ssh.connect(hostname=ssh_host, username=ssh_user, password=ssh_password)

    stdin, stdout, stderr = ssh.exec_command('mysqldump --host={mysql_host} -u {mysql_user} -p{mysql_password} --databases {mysql_databases}'.format(
        mysql_host=mysql_host,
        mysql_user=mysql_user,
        mysql_password=mysql_password,
        mysql_databases=mysql_databases
    ))

    logging.info('Begin writing to file {}'.format(output_file))
    file = open(output_file, 'wb')

    # Wait for the command to terminate
    while not stdout.channel.exit_status_ready():
        # Only print data if there is data to read in the channel
        if stdout.channel.recv_ready():
            rl, wl, xl = select.select([stdout.channel], [], [], 0.0)
            if len(rl) > 0:
                # Print data from stdout
                r = stdout.channel.recv(1024)
                file.write(str(r))
    file.close()
    logging.info('Done writing to file.')
    ssh.close()

if __name__ == '__main__':
    dump_mysql_to_file_via_ssh(
        ssh_host='ssh.example.com',
        ssh_user='',
        ssh_password='',
        mysql_host='',
        mysql_user='',
        mysql_password='',
        mysql_databases='',
        output_file='sebastiannilsson.com.sql'
        )
    sftp_backup(ssh_host='ssh.example.com', ssh_username='', ssh_password='', source_directory='', local_directory='')
Taggad med:

Cpac Systems: Programming for outboard steering and propulsion systems

The project involved solving complex problems and also lots of boat testing around the world (Sweden, Japan and the US). My main tasks were to implement software algorithms, and as a side project I also developed a boat simulator to reduce time spent doing boat testing.