Help pls this is the 2nd sketch for Aruino trying to load.

Hello , as I said in title I don't have any experience loading complicated sketch , so if anyone can help me, please welcome. ( my 1st loaded sketch was the "blink led" ).
I use the arduino 1.6.12 platform. I have read that a library named xxxx must contains at least two files, the xxxx.h and the xxxx.cpp so to be considered as "Library". I am trying to load the following sketch ( these are some lines):

  1. // calipers.c

  2. // for NerdKits with ATmega168

  3. // mike@nerdkits.com

  4. #define F_CPU 14745600

  5. #include <stdio.h>

  6. #include <avr/io.h>

  7. #include <avr/interrupt.h>

  8. #include <avr/pgmspace.h>

  9. #include <inttypes.h>

  10. #include "../libnerdkits/delay.h"

  11. #include "../libnerdkits/lcd.h"
    12.#include "../libnerdkits/uart.h"

  12. // PIN DEFINITIONS:

  13. //

  14. // PB1 -- (inverted) data

  15. // PB2 -- (inverted) clock

  16. // PB3 -- power to calipers

The sketch need to load all these libraries using the command "include", right ? Some of those libraries I have found as zip file and I don't have problem to upload ( i.e. Line 5, stdio.zip ).
The command at Line 6-9 refer to (avr/io.h , avr/interrupt.h , pgmspace.h , etc). Need to upload in a new directory named "avr" ? For these libraries, I can find only the xxx.h , don't find the xxxx.cpp . How is possible to upload only the .h file ? I cannot find any help at this point.
Same, for Lines 10-12. I find only the xxxx.h and not the xxx.cpp . How can I upload it ?

Thanks for your help.
happy new year
Takis

calipers (source code calipers.c).c (4.31 KB)

What's your arduino?

  1. #include <stdio.h>

  2. #include <avr/io.h>

  3. #include <avr/interrupt.h>

  4. #include <avr/pgmspace.h>

  5. #include <inttypes.h>

Those are not libraries. Those files are installed when the IDE is installed; you don't need to install them.

Same, for Lines 10-12. I find only the xxxx.h and not the xxx.cpp . How can I upload it ?

libnerdkits uses c-files, not cpp-files. That is not a problem. What might a problem is the way the includes are organised. To me, it looks like the library was not written with Arduino and Arduino IDE in mind.

You can work around that. The simplest way is probably to dump those .h and .c files in the directory where your sketch is located and change the includes to

  1. #include "delay.h"
  2. #include "lcd.h"
  3. #include "uart.h"

You probably need to change the extension of the c files to cpp.

And next the question why you want to use this? Arduino already provides libraries that contain those functionalities (I base that on the names of the includes, not on the content of the 'libraries').

hello,
is the aduino uno R3.

Hello sterretje, thanks for your help.

These guys ( nerdkits ) they have write this sketch including some functionalities that I can't know if I will find them in Arduino libraries. For example they have put a switch which divide the measured pulses by 2 , also by other switch change the number displayed sign from negative to positive , simple functionalities which I don't know how to include to Arduinos sketch.

Line 6-9. shall will leave these lines as seems in code ? i.e. #include <avr/io.h>
will be found by the compiler ? Need to check if the "avr/" is an existing directory in my pc ?

making all the previous suggestions and changes in code , can I run the "Verify" ( without connect the Arduino and the hardware ) so to check if the sketch will find all the necessary libs and file ?
If something is missing , will get a message ? If all found, will get a message like "successful"

thanks

I tried to verify and it did does not compile :wink: I have no idea what the error message that I got means (I would look it up if it was my code :wink: )

The nerdkits includes don't add anything (as said, the Arduino provides the standard functionalities).

You will have to learn to understand the code and decide based on that what you need and what you don't. You e.g. need all the functions that are in calipers.c.

Below is a reworked version that compiles. Create a new sketch and replace the content with the below; there will be no setup() and no loop(); I added some comments in the main() function to show what ususally goes in setup() and what goes in loop().

The only thing that has changed is replacing the nerdkits' functions in the libraries by the arduino ones, mostly related to serial and lcd.

//#define NERDKITS

#ifndef NERDKITS
// not nerdkits, 'replace' delay_ms by delay
#define delay_ms delay
#endif

#ifndef NERDKITS
// not nerdkits, use arduino LiquidCrystal library
#include <LiquidCrystal.h>
/***************************************
  make sure that your pin out matches !!
***************************************/
#define LCD_D4 7
#define LCD_D5 6
#define LCD_D6 5
#define LCD_D7 4

#define LCD_RS 12
#define LCD_E  11

#define LCD_NUMCOLS 20
#define LCD_NUMROWS 4

// initialize the library with the numbers of the interface pins
LiquidCrystal lcd(LCD_RS, LCD_E, LCD_D4, LCD_D5, LCD_D6, LCD_D7);
#endif

// calipers.c
// for NerdKits with ATmega168
// mike@nerdkits.com

#ifdef NERDKITS
#define F_CPU 14745600
#endif

#include <stdio.h>

#include <avr/io.h>
#include <avr/interrupt.h>
#include <avr/pgmspace.h>
#include <inttypes.h>

#ifdef NERDKITS
#include "delay.h"
#include "lcd.h"
#include "uart.h"
#endif

// PIN DEFINITIONS:
//
// PB1 -- (inverted) data
// PB2 -- (inverted) clock
// PB3 -- power to calipers
// PB4 -- direction switch (pull up)
// PB5 -- zero button (pull up)
// PC1 -- data line MOSFET
// PC3 -- clock line MOSFET

void calipers_power_on()
{
  PORTB |= (1 << PB3);
  DDRB |= (1 << PB3);
}

void calipers_touch_mode()
{
  PORTC |= (1 << PC1);
  delay_ms(100);
  PORTC &= ~(1 << PC1);
}

void calipers_touch_zero()
{
  PORTC |= (1 << PC3);
  delay_ms(100);
  PORTC &= ~(1 << PC3);
}

uint8_t read_bit()
{
  // wait for rising edge of /CLK
  // then sample /DATA
  // return 0 for true 0 (high voltage on /DATA)
  // return 1 for true 1 (low voltage on /DATA)
  // return 2 for timeout error

  uint8_t attempt_counter = 200;
  // at 14.7456 MHz and 8 clocks/loop, 200 takes 108us.
  while (--attempt_counter)
  {
    if ((PINB & (1 << PB2)) != 0)
    {
      // we got rising edge
      break;
    }
  }
  if (attempt_counter == 0)
    return 2;  // timeout error

  // sample a bunch of times and take the best guess
  uint8_t samples = 5;
  uint8_t samples_0 = 0;
  uint8_t samples_1 = 0;
  uint8_t i;
  for (i = 0; i < samples; i++)
  {
    if ((PINB & (1 << PB1)) != 0)
    {
      samples_0++;
    }
    else
    {
      samples_1++;
    }
  }

  if (samples_0 > samples_1)
  {
    return 0;
  }
  else
  {
    return 1;
  }
}

int32_t read_bits()
{
  // read 24 bits
  // LSB first
  // return in a signed int32_t

  uint32_t accumulator = 0;
  uint32_t bitval = 1;
  uint8_t rb;
  uint8_t i;
  for (i = 0; i < 24; i++)
  {
    rb = read_bit();
    if (rb == 2)
    {
      // TIMEOUT
      return (1L << 30);
    }
    else if (rb == 1)
    {
      accumulator |= bitval;
    }
    bitval <<= 1;
  }

  // handle negatives
  if (rb == 1)
  {
    // the MSB was 1 so we've got a negative number!
    // fill the upper 8-bits of the 32-bit
    accumulator |= 0xFF000000L;
  }

  return accumulator;
}

void wait_for_quiet()
{
  // get at least 50us of high on /CLK
  // before returning.
  // not really microseconds -- close enough!
  uint8_t quiet_us = 0;
  while (quiet_us++ < 50)
  {
    if ((PINB & (1 << PB2)) == 0)
    {
      // /CLK is low -- not quiet!
      quiet_us = 0;
    }
  }
  // we made it through 50!
  return;
}

void wait_for_pulse()
{
  // get at least 50us of high on /CLK
  wait_for_quiet();

  // then wait for a falling edge
  while ((PINB & (1 << PB2)) != 0)
  {
    // do nothing
  }
}

int main()
{
  /*********************************
    This part is usually in setup()
  *********************************/

  // activate pull-ups
  PORTB |= (1 << PB1) | (1 << PB2) | (1 << PB4) | (1 << PB5);

  // allow zero, mode pushing
  DDRC |= (1 << PC1) | (1 << PC3);

  // turn on calipers
  calipers_power_on();
  delay_ms(2000);
  calipers_touch_mode();
  delay_ms(100);
  calipers_touch_zero();

  // init serial port
#ifdef NERDKITS
  uart_init();
  FILE uart_stream = FDEV_SETUP_STREAM(uart_putchar, uart_getchar, _FDEV_SETUP_RW);
  stdin = stdout = &uart_stream;
#else
  Serial.begin(115200);
#endif

  // lcd
#ifdef NERDKITS
  lcd_init();
  FILE lcd_stream = FDEV_SETUP_STREAM(lcd_putchar, 0, _FDEV_SETUP_WRITE);
  lcd_clear_and_home();
#else
  lcd.begin(LCD_NUMCOLS, LCD_NUMROWS);
#endif


  /*********************************
    This part is usually in loop()
    The variables would be static
  *********************************/
  int32_t lastpos, tmpr, refpos = 0;
  uint8_t flipdir;
  double lastpos_inches, lastpos_mm;
  while (1)
  {
    wait_for_pulse();
    tmpr = read_bits();
    if (tmpr != (1L << 30))
    {

      // zero?
      if ((PINB & (1 << PB5)) == 0)
        refpos = tmpr;
      // alternate direction?
      flipdir = ((PINB & (1 << PB4)) == 0) ? 1 : 0;


      // calculate position
      lastpos = tmpr - refpos;
      if (flipdir)
        lastpos = -lastpos;

      // translate into inches and mm
      lastpos_inches = lastpos / 20480.0;
      lastpos_mm = lastpos * (25.4 / 20480.0);

      // send over serial port
      printf_P(PSTR("%8ld\t%10.5f\r\n"), lastpos, lastpos_inches);

      // show on LCD
#ifdef NERDKITS
      lcd_line_one();
      fprintf_P(&lcd_stream, PSTR("Smithy 1220XL Z-Axis"));
#else
      lcd.setCursor(0, 0);
      lcd.print(F("Smithy 1220XL Z-Axis"));
#endif

#ifdef NERDKITS
      lcd_line_two();
      fprintf_P(&lcd_stream, PSTR("%9.4f inches    "), lastpos_inches);

      lcd_line_three();
      fprintf_P(&lcd_stream, PSTR("%8.3f  mm        "), lastpos_mm);
#else
      char buffer[16];
      lcd.setCursor(0, 1);
      lcd.print(dtostrf(lastpos_inches, 9, 4, buffer));
      lcd.print(" inches");
      lcd.setCursor(0, 2);
      lcd.print(dtostrf(lastpos_mm, 9, 4, buffer));
      lcd.print(" mm");
#endif

#ifdef NERDKITS
      lcd_line_four();
      if (!flipdir)
      {
        fprintf_P(&lcd_stream, PSTR("+ direction is DOWN "));
      }
      else
      {
        fprintf_P(&lcd_stream, PSTR("+ direction is UP   "));
      }
#else
      lcd.setCursor(0, 3);
      if (!flipdir)
      {
        lcd.print(F("+ direction is DOWN "));
      }
      else
      {
        lcd.print(F("+ direction is UP   "));
      }
#endif
    }
  }

  return 0;
}

The first line (commented out) allows you to compile either the original code or the arduino based version. If you uncomment the line, it will compile the original, else the arduino version.

You can search for NERDKITS to find the changes.

Note that the original was written for a controller running on a 14.7456MHz crystal; the Arduino runs on 16MHz; the read_bit() function might therefor behave slightly different but I don't think it's a worry.

thanks sterretje for your trying. I will follow your suggestion.
Meanwhile I found that using the avr-gcc maybe is possible to compile the calipers.c file.
I have put all these liblaries and files in one folder. I have run the avr-gcc , seems to recognizes everything but with the following error message:

calipers.c : c154: error; expected primary-expression before "." token
calipers.c : c159: error; expected primary-expression before "." token

line 154 contents the following code :

FILE uart_stream = FDEV_SETUP_STREAM(uart_putchar, uart_getchar, _FDEV_SETUP_RW);
stdin = stdout = &uart_stream;

line 159 contents the following code :

FILE lcd_stream = FDEV_SETUP_STREAM(lcd_putchar, 0, _FDEV_SETUP_WRITE);
lcd_clear_and_home();

do you know what this mean and there is a syntax error at this line ?
( i will open a new post asking someone to help me at this point ). I will try your conversion

thanks again