0.1.2 AtomicWeight

This commit is contained in:
rob tillaart 2022-12-31 18:30:42 +01:00
parent ce8751d505
commit 449f943312
10 changed files with 422 additions and 32 deletions

View File

@ -0,0 +1,286 @@
//
// FILE: AtomicWeight.cpp
// AUTHOR: Rob Tillaart
// DATE: 2022-03-09
// VERSION: 0.1.1
// PURPOSE: Arduino library for atomic weights
// URL: https://github.com/RobTillaart/AtomicWeight
#include "AtomicWeight.h"
/////////////////////////////////////////////////////////////////////////
//
// list of elements
// weight = weight * 222.909
//
struct element
{
char name[3];
uint16_t weight;
}
elements[119] =
{
{"n", 225}, // neutronium
{"H", 225},
{"He", 892},
{"Li", 2186},
{"Be", 2009},
{"B", 2410},
{"C", 2677},
{"N", 3122},
{"O", 3566},
{"F", 4235},
{"Ne", 4498},
{"Na", 5125},
{"Mg", 5418},
{"Al", 6014},
{"Si", 6261},
{"P", 6904},
{"S", 7148},
{"Cl", 7903},
{"Ar", 8905},
{"K", 8715},
{"Ca", 8934},
{"Sc", 10021},
{"Ti", 10670},
{"V", 11355},
{"Cr", 11590},
{"Mn", 12246},
{"Fe", 12448},
{"Co", 13137},
{"Ni", 13083},
{"Cu", 14165},
{"Zn", 14580},
{"Ga", 15542},
{"Ge", 16192},
{"As", 16701},
{"Se", 17601},
{"Br", 17811},
{"Kr", 18679},
{"Rb", 19052},
{"Sr", 19531},
{"Y", 19818},
{"Zr", 20335},
{"Nb", 20710},
{"Mo", 21386},
{"Tc", 21845},
{"Ru", 22529},
{"Rh", 22939},
{"Pd", 23722},
{"Ag", 24045},
{"Cd", 25057},
{"In", 25594},
{"Sn", 26462},
{"Sb", 27141},
{"Te", 28443},
{"I", 28288},
{"Xe", 29266},
{"Cs", 29626},
{"Ba", 30611},
{"La", 30963},
{"Ce", 31233},
{"Pr", 31410},
{"Nd", 32152},
{"Pm", 32322},
{"Sm", 33517},
{"Eu", 33874},
{"Gd", 35052},
{"Tb", 35426},
{"Dy", 36223},
{"Ho", 36764},
{"Er", 37284},
{"Tm", 37657},
{"Yb", 38572},
{"Lu", 39002},
{"Hf", 39787},
{"Ta", 40335},
{"W", 40980},
{"Re", 41507},
{"Os", 42404},
{"Ir", 42847},
{"Pt", 43485},
{"Au", 43906},
{"Hg", 44713},
{"Tl", 45559},
{"Pb", 46187},
{"Bi", 46584},
{"Po", 46588},
{"At", 46811},
{"Rn", 49486},
{"Fr", 49709},
{"Ra", 50377},
{"Ac", 50600},
{"Th", 51723},
{"Pa", 51500},
{"U", 53059},
{"Np", 52829},
{"Pu", 54390},
{"Am", 54167},
{"Cm", 55059},
{"Bk", 55059},
{"Cf", 55950},
{"Es", 56173},
{"Fm", 57288},
{"Md", 57511},
{"No", 57733},
{"Lr", 58402},
{"Rf", 58179},
{"Db", 58402},
{"Sg", 59294},
{"Bh", 58848},
{"Hs", 61746},
{"Mt", 59740},
{"Ds", 62637},
{"Rg", 60631},
{"Cn", 63529},
{"Nh", 63752},
{"Fl", 64421},
{"Mc", 64421},
{"Lv", 65312},
{"Ts", 65535},
{"Og", 65535},
};
PTOE::PTOE(uint8_t size)
{
_size = size;
}
uint8_t PTOE::size()
{
return _size;
}
uint8_t PTOE::electrons(uint8_t el)
{
return el;
}
uint8_t PTOE::neutrons(uint8_t el)
{
return round(weight(el) - el);
}
uint8_t PTOE::protons(uint8_t el)
{
return el;
}
float PTOE::weight(uint8_t el)
{
return elements[el].weight * _weightFactor;
}
float PTOE::weight(const char * formula)
{
return weight((char*) formula);
}
float PTOE::weight(char * formula)
{
p = formula;
return _weight('\0');
}
float PTOE::_weight(char sep)
{
float sum = 0;
float w = 0;
char elem[3] = { 0, 0, 0 };
int count = 0;
// char *p = formula;
while (*p != sep)
{
w = 0;
// HANDLE GROUP (...)
if (*p == '(')
{
p++; // skip '('
w = _weight(')');
// Serial.println(w);
p++; // skip ')'
}
else
{
// GET ELEMENT := [ Upper | Upper,lower ]
elem[1] = 0;
if (! isupper(*p)) return 0; // fail
elem[0] = *p;
p++;
if (islower(*p))
{
elem[1] = *p;
p++;
}
int z = find(elem);
if (z == 255) return 0; // fail
w = weight(z);
}
count = 0;
// get optional digits
while (isdigit(*p))
{
count = count * 10 + (*p - '0');
p++;
}
// correct for no digits
if (count == 0) count = 1;
// DEBUG
// Serial.println(w);
// Serial.println(count);
sum += w * count;
}
return sum;
}
char * PTOE::name(uint8_t el)
{
return elements[el].name;
}
uint8_t PTOE::find(const char * abbrev)
{
return find((char *) abbrev);
}
uint8_t PTOE::find(char * abbrev)
{
for (uint8_t i = 0; i < _size; i++)
{
if (strcmp(elements[i].name, abbrev) == 0) return i;
}
return 255;
}
////////////////////////////////////////////////////////////////
//
// DEBUG
//
float PTOE::weightFactor()
{
return _weightFactor;
}
// -- END OF FILE --

View File

@ -3,20 +3,19 @@
// FILE: AtomicWeight.h
// AUTHOR: Rob Tillaart
// DATE: 2022-03-09
// VERSION: 0.1.1
// VERSION: 0.1.2
// PURPOSE: Arduino library for atomic weights
// URL: https://github.com/RobTillaart/AtomicWeight
#include "Arduino.h"
#define ATOMIC_WEIGHT_LIB_VERSION (F("0.1.1"))
#define ATOMIC_WEIGHT_LIB_VERSION (F("0.1.2"))
/////////////////////////////////////////////////////////////////////////
//
// IS THIS THE RIGHT FORMAT?
// or should we build a list of elements
// PERIODIC TABLE OF ELEMENTS Class
//
class PTOE
{
@ -36,6 +35,7 @@ public:
char * name(uint8_t el);
uint8_t find(const char * abbrev);
uint8_t find(char * abbrev);
@ -46,6 +46,9 @@ public:
private:
uint8_t _size;
const float _weightFactor = 1.0 / 222.909;
float _weight(char sep);
char *p; // for _weight().
};

View File

@ -6,6 +6,13 @@ The format is based on [Keep a Changelog](http://keepachangelog.com/)
and this project adheres to [Semantic Versioning](http://semver.org/).
## [0.1.2] - 2023-01-01
- add weight(formula) group () support
- rewrote example
- update readme.md.
- add unit tests
## [0.1.1] - 2022-12-30
- fix offset in some functions
- move code to .cpp file
@ -13,7 +20,6 @@ and this project adheres to [Semantic Versioning](http://semver.org/).
- refactor and clean up a bit.
- update readme.md.
## [0.1.0] - 2022-12-30
- initial release
- renamed class from AtomicWeight to PTOE.

View File

@ -14,7 +14,7 @@ Arduino library for atomic weights.
## Description
This library is mainly as a base for educational purposes.
Learning the periodic table of elements, the abbreviations and weight.
Learning the **periodic table of elements**, the abbreviations and weight.
It also provides the number of electrons, neutrons and protons per element.
Furthermore the library has a **weight()** function, that returns the weight
@ -38,12 +38,15 @@ The PTOE class uses a table that has compressed weight to save RAM
#include "AtomicWeight.h"
```
The parameter **element** in the following functions is 0..118.
(element 0 being a single neutron).
- **PTOE()** Constructor (Periodic Table Of Elements)
- **uint8_t electrons(uint8_t element)** returns the number of electrons of the element.
- **uint8_t neutrons(uint8_t element)** returns the number of neutrons of the element.
- **uint8_t protons(uint8_t element)** returns the number of protons of the element.
- **float weight(uint8_t element)** returns the weight of the element.
The error < 0.3%, table uses "weight compression"/
The error < 0.3%, table uses "weight compression".
- **float weight(char \* formula)** returns the weight of a molecule e.g. "H2O".
Returns 0 if it cannot parse the formula given.
Cannot parse complex formulas with brackets () in it.
@ -51,23 +54,36 @@ Cannot parse complex formulas with brackets () in it.
- **char \* name(uint8_t element)** returns the abbreviation of element.
#### debug
- **float weightFactor()** returns weightFactor.
## weight
#### weight
The **weight(int n)** function returns the weight of a single atom.
The **weight(formula)** function is meant to calculate the weight of a molecule.
It does not care about the order of the atoms.
So "C6H6" is equal to "H6C6" or even "CCCCCCHHHHHH" or "C3H3C3H3".
The latter function does not care about the order of the atoms.
So "C6H6" is equal to "H6C6" or even "CCCCCCHHHHHH" or "C3H3C3H3" etc.
Elements are defined as 1 or two characters long.
The first must be uppercase, the second must be lowercase.
If no number is provided the count of 1 is assumed.
The function returns a float, so to get the integer weight, one should use **round()**.
The functions returns a float, so to get the integer weight, one should use **round()**.
The weight parsing does not support brackets () in the formula so "H2(SO4)2" fails.
If the formula is not parseable it will return a weight of 0.
(Since 0.1.2)
The weight formula parsing experimentally supports brackets () to indicate groups in the formula.
Valid formula's might look as:
- "B" = single element
- "Na" = single element
- "C6" = single element, multiple times
- "H2SO4" compound molecule, no groups
- "C6(COOH)2" compound molecule, with repeating groups
- "YBa2Cu3O7" some superconductor-ish material
#### debug
- **float weightFactor()** returns weightFactor.
## Operation
@ -80,26 +96,25 @@ See examples
#### must
- improve documentation
- add examples
#### should
- extend unit tests
- extend formula parser with () support.
- extend formula parser with error codes?
- add examples
- extend formula parser with error codes.
#### could
- extend unit tests
- state table
- liquid, gas, solid, unknown (2 bits per element) = ~30 bytes
- (short) table of English names
- which ones ?
- function **float massPercentage("H2O", "H")** ~10%
- function **float atomicPercentage("H2O", "H")** ~33%
- performance **find()** ?
- performance functions
- especially **find()** ?
- case (in)sensitive **find()**
- is there a faster data structure.
#### wont (unless)

View File

@ -9,9 +9,13 @@
PTOE ptoe;
char formula1[24] = "C6H6O6";
char formula0[24] = "C6H6O6";
char formula1[24] = "((COH)3)2";
char formula2[24] = "H2SO4";
char formula3[24] = "HHSOOOO";
char formula3[24] = "CuO2";
// char formula4[24] = "(COH)3(COH)2COH";
// char formula4[24] = "(CH)6O6";
char formula4[24] = "xH2"; // fails => 0;
void setup()
{
@ -33,9 +37,13 @@ void setup()
Serial.print(" \t");
Serial.println(ptoe.weight("He6"));
Serial.print("O6");
Serial.print("NaCl");
Serial.print(" \t");
Serial.println(ptoe.weight("O6"));
Serial.println(ptoe.weight("NaCl"));
Serial.print(formula0);
Serial.print(" \t");
Serial.println(ptoe.weight(formula0));
Serial.print(formula1);
Serial.print(" \t");
@ -48,6 +56,10 @@ void setup()
Serial.print(formula3);
Serial.print(" \t");
Serial.println(ptoe.weight(formula3));
Serial.print(formula4);
Serial.print(" \t");
Serial.println(ptoe.weight(formula4));
}
void loop()

View File

@ -0,0 +1,12 @@
UNO, 1.8.19
atomic_weight_formula.ino
ATOMIC_WEIGHT_LIB_VERSION: 0.1.1
C 12.01
C6 72.06
He6 24.01
O6 95.99
C6H6O6 174.10
H2SO4 98.08
HHSOOOO 98.08

View File

@ -8,9 +8,9 @@ PTOE KEYWORD1
# Methods and Functions (KEYWORD2)
size KEYWORD2
electrons KEYWORD2
protons KEYWORD2
neutrons KEYWORD2
electrons KEYWORD2
weight KEYWORD2
name KEYWORD2

View File

@ -15,7 +15,7 @@
"type": "git",
"url": "https://github.com/RobTillaart/AtomicWeight.git"
},
"version": "0.1.1",
"version": "0.1.2",
"license": "MIT",
"frameworks": "arduino",
"platforms": "*",

View File

@ -1,5 +1,5 @@
name=AtomicWeight
version=0.1.1
version=0.1.2
author=Rob Tillaart <rob.tillaart@gmail.com>
maintainer=Rob Tillaart <rob.tillaart@gmail.com>
sentence=Arduino library for AtomicWeight

View File

@ -63,8 +63,64 @@ unittest(test_constructor)
unittest(test_find)
{
PTOE ptoe;
assertEqual( 0, ptoe.find("n"));
assertEqual( 1, ptoe.find("H"));
assertEqual( 6, ptoe.find("C"));
assertEqual(10, ptoe.find("Ne"));
assertEqual(18, ptoe.find("Ar"));
assertEqual(26, ptoe.find("Fe"));
assertEqual(36, ptoe.find("Kr"));
assertEqual(47, ptoe.find("Ag"));
assertEqual(54, ptoe.find("Xe"));
assertEqual(79, ptoe.find("Au"));
assertEqual(92, ptoe.find("U"));
assertEqual(1, ptoe.find("H"));
assertEqual(255, ptoe.find("XX")); // Fail test
}
unittest(test_basic_atom)
{
PTOE ptoe;
int el = 0;
// NEUTRONIUM
assertEqual("n", ptoe.name(el));
assertEqual( 0, ptoe.electrons(el));
assertEqual( 1, ptoe.neutrons(el));
assertEqual( 0, ptoe.protons(el));
assertEqual( 1, round(ptoe.weight(el)));
// HYDROGEN
el = 1;
assertEqual("H", ptoe.name(el));
assertEqual( 1, ptoe.electrons(el));
assertEqual( 0, ptoe.neutrons(el));
assertEqual( 1, ptoe.protons(el));
assertEqual( 1, round(ptoe.weight(el)));
// URANIUM
el = 92;
assertEqual("U", ptoe.name(el));
assertEqual( 92, ptoe.electrons(el));
assertEqual(146, ptoe.neutrons(el));
assertEqual( 92, ptoe.protons(el));
assertEqual(238, round(ptoe.weight(el)));
}
unittest(test_weight_formula)
{
PTOE ptoe;
assertEqualFloat( 22.9914, ptoe.weight("Na"), 0.1);
assertEqualFloat( 58.4454, ptoe.weight("NaCl"), 0.1);
assertEqualFloat( 100.081, ptoe.weight("CaCO3"), 0.1);
assertEqualFloat( 98.0759, ptoe.weight("H2SO4"), 0.1);
assertEqualFloat( 116.065, ptoe.weight("C2H2(COOH)2"), 0.1);
assertEqualFloat( 666.178, ptoe.weight("YBa2Cu3O7"), 0.1);
assertEqualFloat( 72.1146, ptoe.weight("C(O(H2)2)3"), 0.1);
}